diff --git a/UIX/Microsoft/Iris/Application.cs b/UIX/Microsoft/Iris/Application.cs index 960663b..fa337fc 100644 --- a/UIX/Microsoft/Iris/Application.cs +++ b/UIX/Microsoft/Iris/Application.cs @@ -6,6 +6,7 @@ using Microsoft.Iris.Animations; using Microsoft.Iris.Data; +using Microsoft.Iris.Debug; using Microsoft.Iris.Input; using Microsoft.Iris.Library; using Microsoft.Iris.Markup; @@ -135,7 +136,11 @@ namespace Microsoft.Iris get => DllResources.StaticDllResourcesOnly; } - public static Debug.DebugSettings DebugSettings { get; } = new(); + public static DebugSettings DebugSettings { get; } = new(); + + internal static IDebuggerServer Debugger { get; private set; } + + public static event EventHandler DebuggerServerReady; public static void Initialize() { @@ -187,7 +192,12 @@ namespace Microsoft.Iris ErrorManager.OnErrors += new NotifyErrorBatch(NotifyErrorBatchHandler); Debug.Trace.Initialize(); - Debug.BridgeServer.Start(null); + + if (DebugSettings.DebugConnectionUri != null) + { + Debugger = new ZmqDebuggerServer(DebugSettings.DebugConnectionUri); + DebuggerServerReady?.Invoke(Debugger, EventArgs.Empty); + } MarkupSystem.Startup(!fullInitialization); StaticServices.Initialize(); diff --git a/UIX/Microsoft/Iris/Debug/BridgeServer.cs b/UIX/Microsoft/Iris/Debug/BridgeServer.cs deleted file mode 100644 index 43b87ec..0000000 --- a/UIX/Microsoft/Iris/Debug/BridgeServer.cs +++ /dev/null @@ -1,58 +0,0 @@ -using CoreRemoting; -using CoreRemoting.DependencyInjection; -using CoreRemoting.Serialization.Binary; -using System; - -namespace Microsoft.Iris.Debug; - -internal class BridgeServer : IBridge, IDisposable -{ - private static RemotingServer _server; - - public static IBridge Current { get; private set; } - - public event EventHandler InterpreterStep; - public event Action DispatcherStep; - - public static void Start(ServerConfig config) - { - _server = new RemotingServer(new ServerConfig - { - HostName = "localhost", - NetworkPort = 9090, - MessageEncryption = false, - Serializer = new BinarySerializerAdapter(), - RegisterServicesAction = container => - { - container.RegisterService(ServiceLifetime.Singleton); - } - }); - - Current = _server.ServiceRegistry.GetService(); - - _server.Error += OnServerError; - _server.BeforeCall += (_, ctx) => - { - - }; - - _server.Start(); - } - - private static void OnServerError(object sender, Exception e) - { - - } - - public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry) - { - InterpreterStep?.Invoke(context, entry); - } - - public void LogDispatcher(string message) - { - DispatcherStep?.Invoke(message); - } - - public void Dispose() => _server.Dispose(); -} diff --git a/UIX/Microsoft/Iris/Debug/DebugSettings.cs b/UIX/Microsoft/Iris/Debug/DebugSettings.cs index 0a6d404..d3a5018 100644 --- a/UIX/Microsoft/Iris/Debug/DebugSettings.cs +++ b/UIX/Microsoft/Iris/Debug/DebugSettings.cs @@ -1,5 +1,4 @@ -using CoreRemoting; -using System.Collections.Generic; +using System.Collections.Generic; using System.Xml; #if NET40_OR_GREATER || NET6_0_OR_GREATER @@ -23,7 +22,7 @@ namespace Microsoft.Iris.Debug public List Breakpoints { get; } = new List(); - public ServerConfig DebugServerConfig { get; set; } + public string DebugConnectionUri { get; set; } } public class DecompilationResult diff --git a/UIX/Microsoft/Iris/Debug/DebuggerMessageType.cs b/UIX/Microsoft/Iris/Debug/DebuggerMessageType.cs new file mode 100644 index 0000000..2401fa8 --- /dev/null +++ b/UIX/Microsoft/Iris/Debug/DebuggerMessageType.cs @@ -0,0 +1,9 @@ +namespace Microsoft.Iris.Debug; + +public enum DebuggerMessageType : int +{ + Null = 0, + + InterpreterOpCode, + DispatcherStep, +} diff --git a/UIX/Microsoft/Iris/Debug/IBridge.cs b/UIX/Microsoft/Iris/Debug/IBridge.cs deleted file mode 100644 index 18a2765..0000000 --- a/UIX/Microsoft/Iris/Debug/IBridge.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace Microsoft.Iris.Debug; - -/// -/// The contract between the UIX runtime and debuggers. -/// -public interface IBridge -{ - /// - /// Fired when the UIX interpreter steps forward. - /// - event EventHandler InterpreterStep; - - /// - /// Fired when the UIX dispatcher executes another call from the queue. - /// - event Action DispatcherStep; - - /// - /// Logs the context, opcode, and arguments of an instruction - /// executed by Microsoft.Iris.Markup.Interpreter. - /// - /// - /// - public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry); - - /// - /// Logs the string representation of a dispatcher step. - /// - /// - public void LogDispatcher(string message); -} diff --git a/UIX/Microsoft/Iris/Debug/IDebuggerClient.cs b/UIX/Microsoft/Iris/Debug/IDebuggerClient.cs new file mode 100644 index 0000000..f012698 --- /dev/null +++ b/UIX/Microsoft/Iris/Debug/IDebuggerClient.cs @@ -0,0 +1,17 @@ +using Microsoft.Iris.Debug.Data; +using System; + +namespace Microsoft.Iris.Debug; + +public interface IDebuggerClient +{ + /// + /// Fired when the UIX interpreter steps forward. + /// + event EventHandler InterpreterStep; + + /// + /// Fired when the UIX dispatcher executes another call from the queue. + /// + event Action DispatcherStep; +} diff --git a/UIX/Microsoft/Iris/Debug/IDebuggerServer.cs b/UIX/Microsoft/Iris/Debug/IDebuggerServer.cs new file mode 100644 index 0000000..f7cf3c8 --- /dev/null +++ b/UIX/Microsoft/Iris/Debug/IDebuggerServer.cs @@ -0,0 +1,18 @@ +using Microsoft.Iris.Debug.Data; + +namespace Microsoft.Iris.Debug; + +internal interface IDebuggerServer +{ + /// + /// Logs the context, opcode, and arguments of an instruction + /// executed by Microsoft.Iris.Markup.Interpreter. + /// + public void LogInterpreterOpCode(object context, InterpreterEntry entry); + + /// + /// Logs the string representation of a dispatcher step. + /// + /// + public void LogDispatcher(string message); +} diff --git a/UIX/Microsoft/Iris/Debug/ZmqDebuggerClient.cs b/UIX/Microsoft/Iris/Debug/ZmqDebuggerClient.cs new file mode 100644 index 0000000..03b110b --- /dev/null +++ b/UIX/Microsoft/Iris/Debug/ZmqDebuggerClient.cs @@ -0,0 +1,56 @@ +using Microsoft.Iris.Debug.Data; +using NetMQ; +using NetMQ.Sockets; +using System; +using System.Text; + +namespace Microsoft.Iris.Debug; + +public class ZmqDebuggerClient : IDebuggerClient, IDisposable +{ + private readonly SubscriberSocket _subSocket; + + public event EventHandler InterpreterStep; + public event Action DispatcherStep; + + public ZmqDebuggerClient(string connectionUri) + { + _subSocket = new(); + _subSocket.Connect(connectionUri); + _subSocket.SubscribeToAnyTopic(); + + System.Threading.Thread th = new(MessageRecieveLoop); + th.Start(); + } + + public void Dispose() => _subSocket.Dispose(); + + private void MessageRecieveLoop() + { + while (!_subSocket.IsDisposed) + { + var type = RecieveDebuggerMessage(_subSocket, out var bytes); + + switch (type) + { + case DebuggerMessageType.InterpreterOpCode: + string entry = Encoding.Unicode.GetString(bytes); + InterpreterStep?.Invoke(this, null); + break; + + case DebuggerMessageType.DispatcherStep: + string message = Encoding.Unicode.GetString(bytes); + DispatcherStep?.Invoke(message); + break; + } + } + } + + private DebuggerMessageType RecieveDebuggerMessage(SubscriberSocket socket, out byte[] bytes) + { + var frames = socket.ReceiveMultipartBytes(2); + + bytes = frames[1]; + return (DebuggerMessageType)BitConverter.ToInt32(frames[0], 0); + } +} diff --git a/UIX/Microsoft/Iris/Debug/ZmqDebuggerServer.cs b/UIX/Microsoft/Iris/Debug/ZmqDebuggerServer.cs new file mode 100644 index 0000000..c7455e6 --- /dev/null +++ b/UIX/Microsoft/Iris/Debug/ZmqDebuggerServer.cs @@ -0,0 +1,48 @@ +using NetMQ; +using NetMQ.Sockets; +using System; +using System.Text; + +namespace Microsoft.Iris.Debug; + +internal class ZmqDebuggerServer : IDebuggerServer, IDisposable +{ + public static IDebuggerServer Current { get; private set; } + + private readonly PublisherSocket _pubSocket; + private readonly byte[][] _messageFrame = new byte[2][]; + + public ZmqDebuggerServer(string connectionUri) + { + _pubSocket = new(); + _pubSocket.Bind(connectionUri); + + Current = this; + } + + public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry) + { + SendDebuggerMessage(DebuggerMessageType.InterpreterOpCode, entry.ToString()); + } + + public void LogDispatcher(string message) + { + SendDebuggerMessage(DebuggerMessageType.DispatcherStep, message); + } + + public void Dispose() => _pubSocket.Dispose(); + + private void SendDebuggerMessage(DebuggerMessageType type, string message, Encoding encoding = null) + { + var messageBytes = (encoding ?? Encoding.Unicode).GetBytes(message); + SendDebuggerMessage(type, messageBytes); + } + + private void SendDebuggerMessage(DebuggerMessageType type, byte[] bytes) + { + _messageFrame[0] = BitConverter.GetBytes((int)type); + _messageFrame[1] = bytes; + + _pubSocket.SendMultipartBytes(_messageFrame); + } +} diff --git a/UIX/Microsoft/Iris/Markup/Interpreter.cs b/UIX/Microsoft/Iris/Markup/Interpreter.cs index cb8d5a5..7a6680e 100644 --- a/UIX/Microsoft/Iris/Markup/Interpreter.cs +++ b/UIX/Microsoft/Iris/Markup/Interpreter.cs @@ -66,7 +66,7 @@ namespace Microsoft.Iris.Markup bool errorsDetected = false; object result = null; bool wasInDebugState = false; - bool debugging = BridgeServer.Current != null; + bool debugging = Application.Debugger != null; while (!errorsDetected) { @@ -670,7 +670,7 @@ namespace Microsoft.Iris.Markup } } - BridgeServer.Current?.LogInterpreterOpCode(opCode, entry); + Application.Debugger?.LogInterpreterOpCode(opCode, entry); } while (stack.Count > count) { @@ -1630,7 +1630,7 @@ namespace Microsoft.Iris.Markup } } - BridgeServer.Current?.LogInterpreterOpCode(opCode, entry); + Application.Debugger?.LogInterpreterOpCode(opCode, entry); if (stack.Count != xmlStack.Count) throw new InvalidOperationException( diff --git a/UIX/Microsoft/Iris/Queues/Dispatcher.cs b/UIX/Microsoft/Iris/Queues/Dispatcher.cs index 6fb5cfe..0efc4a9 100644 --- a/UIX/Microsoft/Iris/Queues/Dispatcher.cs +++ b/UIX/Microsoft/Iris/Queues/Dispatcher.cs @@ -73,7 +73,7 @@ namespace Microsoft.Iris.Queues QueueItem nextItem = queue.GetNextItem(); if (nextItem != null) { - BridgeServer.Current.LogDispatcher(nextItem.ToDebugPacketString()); + Application.Debugger.LogDispatcher(nextItem.ToDebugPacketString()); nextItem.Dispatch(); } else diff --git a/UIX/UIX.csproj b/UIX/UIX.csproj index c56538e..1ae1524 100644 --- a/UIX/UIX.csproj +++ b/UIX/UIX.csproj @@ -10,7 +10,7 @@ - +