Start using PairSockets for two-way debug communication

This commit is contained in:
Yoshi Askharoun
2023-05-29 20:19:31 -05:00
parent a61e1e63a9
commit d01235e3f4
3 changed files with 35 additions and 21 deletions
@@ -0,0 +1,81 @@
using Microsoft.Iris.Debug;
using Microsoft.Iris.Debug.Data;
using NetMQ;
using NetMQ.Sockets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
namespace Microsoft.Iris.Debug.NetMQ;
public class ZmqDebuggerClient : IDebuggerClient, IDisposable
{
private List<byte[]> _frames = new(2);
private readonly PairSocket _socket;
private readonly IFormatter _formatter;
public string ConnectionUri { get; }
public event EventHandler<InterpreterEntry> InterpreterStep;
public event Action<string> DispatcherStep;
public ZmqDebuggerClient(string connectionUri)
{
ConnectionUri = connectionUri ?? DebugRemoting.DEFAULT_TCP_CLIENT_URI;
_socket = new();
_socket.Connect(connectionUri);
_formatter = DebugRemoting.CreateBsonFormatter();
System.Threading.Thread th = new(MessageRecieveLoop);
th.Start();
}
public void Dispose() => _socket.Dispose();
private void MessageRecieveLoop()
{
while (!_socket.IsDisposed)
{
DebuggerMessageType type;
byte[] bytes;
while (!TryRecieveDebuggerMessage(out type, out bytes))
;
switch (type)
{
case DebuggerMessageType.InterpreterOpCode:
{
using MemoryStream stream = new(bytes);
var entry = (InterpreterEntry)_formatter.Deserialize(stream);
InterpreterStep?.Invoke(this, entry);
}
break;
case DebuggerMessageType.DispatcherStep:
string message = Encoding.Unicode.GetString(bytes);
DispatcherStep?.Invoke(message);
break;
}
}
}
private bool TryRecieveDebuggerMessage(out DebuggerMessageType type, out byte[] bytes)
{
if (!_socket.IsDisposed && _socket.TryReceiveMultipartBytes(ref _frames, 2))
{
type = (DebuggerMessageType)BitConverter.ToInt32(_frames[0], 0);
bytes = _frames[1];
return true;
}
type = default;
bytes = null;
return false;
}
internal static IFormatter CreateFormatter() => new BsonFormatter(new StreamingContext(StreamingContextStates.Remoting));
}
@@ -0,0 +1,56 @@
using NetMQ;
using NetMQ.Sockets;
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
namespace Microsoft.Iris.Debug.NetMQ;
internal class ZmqDebuggerServer : IDebuggerServer, IDisposable
{
public static IDebuggerServer Current { get; private set; }
private readonly PairSocket _socket;
private readonly byte[][] _messageFrame = new byte[2][];
private readonly IFormatter _formatter;
public ZmqDebuggerServer(string connectionUri)
{
_socket = new();
_socket.Bind(connectionUri ?? DebugRemoting.DEFAULT_TCP_SERVER_URI);
_formatter = DebugRemoting.CreateBsonFormatter();
Current = this;
}
public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry)
{
using MemoryStream entryStream = new();
_formatter.Serialize(entryStream, entry);
SendDebuggerMessage(DebuggerMessageType.InterpreterOpCode, entryStream.ToArray());
}
public void LogDispatcher(string message)
{
SendDebuggerMessage(DebuggerMessageType.DispatcherStep, message);
}
public void Dispose() => _socket.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;
_socket.SendMultipartBytes(_messageFrame);
}
}