Skip to content

Commit 9809670

Browse files
authored
Improve handling of debugging WebSocket messages (#1258)
1 parent a1ff0ed commit 9809670

File tree

3 files changed

+45
-30
lines changed

3 files changed

+45
-30
lines changed

package-lock.json

Lines changed: 18 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,7 @@
16851685
"@types/mocha": "^7.0.2",
16861686
"@types/node": "^14.18.0",
16871687
"@types/vscode": "1.75.0",
1688-
"@types/ws": "^7.2.5",
1688+
"@types/ws": "8.5.4",
16891689
"@types/xmldom": "^0.1.29",
16901690
"@typescript-eslint/eslint-plugin": "^4.32.0",
16911691
"@typescript-eslint/parser": "^4.32.0",
@@ -1720,6 +1720,6 @@
17201720
"@vscode/debugadapter": "^1.61.0",
17211721
"@vscode/debugprotocol": "^1.61.0",
17221722
"vscode-extension-telemetry": "^0.1.6",
1723-
"ws": "^7.4.6"
1723+
"ws": "^8.14.2"
17241724
}
17251725
}

src/debug/dbgp.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,23 @@ export class DbgpConnection extends EventEmitter {
2020
private _chunks: Buffer[];
2121
private _dataLength: number;
2222
private _parser: DOMParser;
23+
private _messages: Buffer[] = [];
24+
private _processingMessages = false;
2325

2426
public constructor(socket: WebSocket) {
2527
super();
2628
this._socket = socket;
2729
this._parsingState = ParsingState.DataLength;
2830
this._chunksDataLength = 0;
2931
this._chunks = [];
30-
socket.on("message", (data: string): void => this._handleDataChunk(Buffer.from(data)));
32+
socket.on("message", (data: string): void => {
33+
this._messages.push(Buffer.from(data));
34+
if (!this._processingMessages) {
35+
this._processingMessages = true;
36+
this._handleDataChunk();
37+
this._processingMessages = false;
38+
}
39+
});
3140
socket.on("error", (error: Error): boolean => this.emit("error", error));
3241
socket.on("close", (): boolean => this.emit("close"));
3342
this._parser = new DOMParser({
@@ -61,7 +70,9 @@ export class DbgpConnection extends EventEmitter {
6170
});
6271
}
6372

64-
private _handleDataChunk(data: Buffer) {
73+
private _handleDataChunk() {
74+
if (!this._messages.length) return; // Shouldn't ever happen
75+
const data: Buffer = this._messages.shift();
6576
if (this._parsingState === ParsingState.DataLength) {
6677
// does data contain a NULL byte?
6778
const separatorIndex = data.indexOf("|");
@@ -80,11 +91,13 @@ export class DbgpConnection extends EventEmitter {
8091
if (data.length > separatorIndex + 1) {
8192
// handle the rest of the packet as part of the response
8293
const rest = data.slice(separatorIndex + 1, this._dataLength + separatorIndex + 1);
83-
this._handleDataChunk(rest);
94+
this._messages.unshift(rest);
95+
this._handleDataChunk();
8496
// more then one data chunk in one message
8597
const restData = data.slice(this._dataLength + separatorIndex + 1);
8698
if (restData.length) {
87-
this._handleDataChunk(restData);
99+
this._messages.unshift(restData);
100+
this._handleDataChunk();
88101
}
89102
}
90103
} else {
@@ -99,7 +112,7 @@ export class DbgpConnection extends EventEmitter {
99112
// append the last piece of the response
100113
const lastResponsePiece = data.slice(0, this._dataLength - this._chunksDataLength);
101114
this._chunks.push(lastResponsePiece);
102-
this._chunksDataLength += data.length;
115+
this._chunksDataLength += lastResponsePiece.length;
103116
const response = Buffer.concat(this._chunks, this._chunksDataLength).toString("ascii");
104117
// call response handler
105118
const xml = iconv.decode(Buffer.from(response, "base64"), ENCODING);
@@ -110,17 +123,19 @@ export class DbgpConnection extends EventEmitter {
110123
this._chunksDataLength = 0;
111124
// switch to data length parsing state
112125
this._parsingState = ParsingState.DataLength;
113-
// if data contains more info (except the NULL byte)
114-
if (data.length > lastResponsePiece.length + 1) {
115-
// handle the rest of the packet (after the NULL byte) as data length
116-
const rest = data.slice(lastResponsePiece.length + 1);
117-
this._handleDataChunk(rest);
126+
// if data contains more info
127+
if (data.length > lastResponsePiece.length) {
128+
// handle the rest of the packet as data length
129+
const rest = data.slice(lastResponsePiece.length);
130+
this._messages.unshift(rest);
131+
this._handleDataChunk();
118132
}
119133
} else {
120134
// NO -> this is not the whole response yet. We buffer it and wait for the next data event.
121135
this._chunks.push(data);
122136
this._chunksDataLength += data.length;
123137
}
124138
}
139+
while (this._messages.length) this._handleDataChunk();
125140
}
126141
}

0 commit comments

Comments
 (0)