Skip to content

Commit b896ddf

Browse files
committed
Handle multiple protobuf messages in the same grpc request
1 parent 8c31a05 commit b896ddf

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

src/services/ui-worker-formatters.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
import * as beautifyXml from 'xml-beautifier';
77

88
import { bufferToHex, bufferToString, getReadableSize } from '../util/buffer';
9-
import { parseRawProtobuf, parseGrpcProtobuf } from '../util/protobuf';
9+
import { parseRawProtobuf, extractProtobufFromGrpc } from '../util/protobuf';
1010

1111
const truncationMarker = (size: string) => `\n[-- Truncated to ${size} --]`;
1212
const FIVE_MB = 1024 * 1024 * 5;
@@ -94,7 +94,10 @@ const WorkerFormatters = {
9494
}, 2);
9595
},
9696
'grpc-proto': (content: Buffer) => {
97-
const data = parseGrpcProtobuf(content);
97+
const protobufMessages = extractProtobufFromGrpc(content);
98+
99+
let data = protobufMessages.map((msg) => parseRawProtobuf(msg, { prefix: '' }));
100+
if (data.length === 1) data = data[0];
98101

99102
return JSON.stringify(data, (_key, value) => {
100103
// Buffers have toJSON defined, so arrive here in JSONified form:

src/util/protobuf.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,26 @@ export function isProbablyProtobuf(input: Uint8Array) {
2828

2929
export const parseRawProtobuf = parseRawProto;
3030

31+
// GRPC message structure:
3132
// The repeated sequence of Length-Prefixed-Message items is delivered in DATA frames
32-
3333
// Length-Prefixed-Message → Compressed-Flag Message-Length Message
3434
// Compressed-Flag → 0 / 1 ; encoded as 1 byte unsigned integer
3535
// Message-Length → {length of Message} ; encoded as 4 byte unsigned integer (big endian)
3636
// Message → *{binary octet}
37-
export const parseGrpcProtobuf = (input: Buffer) => {
38-
if (input.readInt8() != 0) {
39-
// TODO support compressed gRPC messages?
40-
throw new Error("compressed gRPC messages not yet supported")
37+
export const extractProtobufFromGrpc = (input: Buffer) => {
38+
const protobufMessasges: Buffer[] = [];
39+
40+
while (input.length > 0) {
41+
if (input.readInt8() != 0) {
42+
throw new Error("Compressed gRPC messages not yet supported")
43+
}
44+
45+
const length = input.readInt32BE(1);
46+
protobufMessasges.push(input.slice(5, 5 + length));
47+
input = input.subarray(5 + length);
4148
}
42-
const length = input.readInt32BE(1);
43-
input = input.slice(5, 5+length);
4449

45-
return parseRawProtobuf(input, {
46-
prefix: ''
47-
});
50+
return protobufMessasges;
4851
}
4952

5053
export const isValidProtobuf = (input: Uint8Array) => {

0 commit comments

Comments
 (0)