Debugger Socket
The debugger socket is a plugin that instantiates a customizable debugger proxy and creates a persistent bi-directional connection between the debugger and the running process.
This article discusses the API of the debug socket plugin and how to use it in your debugger implementation plugin. This is what the overall debugger architecture looks like.
Setting Up a Connection
The socket starts by trying to connect (via TCP) to a port determined by adding one to the debug port that is specified by the runner. If a connection is made the connection process is done and the connect
event is fired.
If the port is not open, the socket assumes the proxy process is not yet running. The socket will start a node process that runs the source code provided by your debugger implementation plugin's getProxySource() function. Once the proxy process is started the socket will once again try to connect to the specified port. This must not fail. If it does fail, the end
event is fired and the socket will attempt to connect, ad infinitum. When the connection succeeds the connect
event is fired.
The debugger implementation is responsible for calling connect()
to initiate the connection to the proxy.
socket.connect();
socket.once("connect", function(){
console.log("Connected");
});
socket.on("data", function(chunk){
console.log("Received", chunk);
});
Note that the v8 debugger doesn't listen to the
connect
event but only listens to thedata
event as thev8
debugger always sends data first on connect. When reconnecting the socket will emit the data event with an empty message.
Connection Cycle
There are five events that indicate a change in the connection state; connect
, away
, beforeBack
, back
and end
.
The away
and back
events are fired when the connection is temporarily lost and then regained, respectively. There can be a considerable time between the two events and a debugger implementation must sync the debugger's state again after this happens (see also the sync() function).
The end
event is fired when a connection failed which implies that any debug session is destroyed. A debugger implementation must keep track of all the debug commands it has sent and must call the callbacks with an error object in the end
event.
socket.on("end", function(){
pendingQueue.forEach(function(item) {
item.callback(new Error("Debug Session Ended"));
});
});
The beforeBack
event fires prior to the back
event and must be used by a debugger to retry those commands that have not yet been confirmed to have been received by the debugger.
socket.on("beforeBack", function(){
pendingQueue.forEach(function(item) {
retry(item);
});
});
Reconnecting
Managing reconnects to an existing debug process is the primary reason for the socket and proxy. The proxy will survive a user's session; when a user disconnects (even for hours) and later returns, the debugger proxy is still running and the client can connect to it via the connection logic as described above.
Connection State
There are three connection states that are available as constants on the socket.
socket.DISCONNECTED
socket.CONNECTED
socket.CONNECTING
Test for the current state of the socket using the attached
property.
socket.connected == socket.CONNECTING
Getting a Reference to the Socket
You'll get a reference to the socket in the attach() function of your debugger plugin.
var socket;
function attach(_socket, reconnect, callback) {
socket = _socket;
In this example we store the socket reference in a variable that is local to the plugin. This allows you to reference the socket outside of the attach()
function as well. You'll most likely need the reference in the detach()
function.
Sending Data
Send any utf-8
data via the socket using the send()
method.
socket.send("{ json: true }");
Updated less than a minute ago