@whitewall/blip-sdk 0.0.142 → 0.0.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/sender/enveloperesolver.js +1 -1
- package/dist/cjs/sender/tcp/json-parser.js +50 -0
- package/dist/cjs/sender/tcp/json-parser.js.map +1 -0
- package/dist/cjs/sender/tcp/tcpsender.js +4 -54
- package/dist/cjs/sender/tcp/tcpsender.js.map +1 -1
- package/dist/esm/sender/enveloperesolver.js +1 -1
- package/dist/esm/sender/tcp/json-parser.js +47 -0
- package/dist/esm/sender/tcp/json-parser.js.map +1 -0
- package/dist/esm/sender/tcp/tcpsender.js +4 -54
- package/dist/esm/sender/tcp/tcpsender.js.map +1 -1
- package/dist/types/sender/tcp/json-parser.d.ts +6 -0
- package/dist/types/sender/tcp/json-parser.d.ts.map +1 -0
- package/dist/types/sender/tcp/tcpsender.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/sender/enveloperesolver.ts +1 -1
- package/src/sender/tcp/json-parser.ts +50 -0
- package/src/sender/tcp/tcpsender.ts +5 -58
|
@@ -22,7 +22,7 @@ class EnvelopeResolver {
|
|
|
22
22
|
this.resolveEnvelopeResponse(id, new Error(`Envelope response timed out after ${timeoutSeconds} seconds`));
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
},
|
|
25
|
+
}, 5000);
|
|
26
26
|
}
|
|
27
27
|
async resolve(envelope) {
|
|
28
28
|
const deferred = this.waitingEnvelopeResponseResolvers[envelope.id];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tryParseJSON = tryParseJSON;
|
|
4
|
+
function tryParseJSON(buffer) {
|
|
5
|
+
const parsedObjects = [];
|
|
6
|
+
let braceCount = 0;
|
|
7
|
+
let inString = false;
|
|
8
|
+
let escaped = false;
|
|
9
|
+
let objectStart = -1;
|
|
10
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
11
|
+
const ch = buffer[i];
|
|
12
|
+
if (inString) {
|
|
13
|
+
if (escaped) {
|
|
14
|
+
escaped = false;
|
|
15
|
+
// backslash '\'
|
|
16
|
+
}
|
|
17
|
+
else if (ch === 0x5c) {
|
|
18
|
+
escaped = true;
|
|
19
|
+
// double quote '"'
|
|
20
|
+
}
|
|
21
|
+
else if (ch === 0x22) {
|
|
22
|
+
inString = false;
|
|
23
|
+
}
|
|
24
|
+
// double quote '"'
|
|
25
|
+
}
|
|
26
|
+
else if (ch === 0x22) {
|
|
27
|
+
inString = true;
|
|
28
|
+
// opening brace '{'
|
|
29
|
+
}
|
|
30
|
+
else if (ch === 0x7b) {
|
|
31
|
+
if (braceCount === 0) {
|
|
32
|
+
objectStart = i;
|
|
33
|
+
}
|
|
34
|
+
braceCount++;
|
|
35
|
+
// closing brace '}'
|
|
36
|
+
}
|
|
37
|
+
else if (ch === 0x7d) {
|
|
38
|
+
braceCount--;
|
|
39
|
+
if (braceCount === 0 && objectStart !== -1) {
|
|
40
|
+
// full object from objectStart..i
|
|
41
|
+
parsedObjects.push(JSON.parse(buffer.subarray(objectStart, i + 1).toString('utf-8')));
|
|
42
|
+
objectStart = -1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// any leftover (partial) object
|
|
47
|
+
const remainingBuffer = objectStart >= 0 ? buffer.subarray(objectStart) : Buffer.alloc(0);
|
|
48
|
+
return { parsedObjects, remainingBuffer };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=json-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-parser.js","sourceRoot":"","sources":["../../../../src/sender/tcp/json-parser.ts"],"names":[],"mappings":";;AAKA,oCA4CC;AA5CD,SAAgB,YAAY,CAAI,MAA2B;IACvD,MAAM,aAAa,GAAa,EAAE,CAAA;IAClC,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,IAAI,WAAW,GAAG,CAAC,CAAC,CAAA;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QAEpB,IAAI,QAAQ,EAAE,CAAC;YACX,IAAI,OAAO,EAAE,CAAC;gBACV,OAAO,GAAG,KAAK,CAAA;gBACf,gBAAgB;YACpB,CAAC;iBAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,GAAG,IAAI,CAAA;gBACd,mBAAmB;YACvB,CAAC;iBAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACrB,QAAQ,GAAG,KAAK,CAAA;YACpB,CAAC;YACD,mBAAmB;QACvB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,QAAQ,GAAG,IAAI,CAAA;YACf,oBAAoB;QACxB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;gBACnB,WAAW,GAAG,CAAC,CAAA;YACnB,CAAC;YACD,UAAU,EAAE,CAAA;YACZ,oBAAoB;QACxB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,UAAU,EAAE,CAAA;YACZ,IAAI,UAAU,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzC,kCAAkC;gBAClC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAM,CAAC,CAAA;gBAC1F,WAAW,GAAG,CAAC,CAAC,CAAA;YACpB,CAAC;QACL,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,MAAM,eAAe,GAAG,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACzF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAA;AAC7C,CAAC"}
|
|
@@ -5,6 +5,7 @@ const bliperror_ts_1 = require("../bliperror.js");
|
|
|
5
5
|
const sender_ts_1 = require("../sender.js");
|
|
6
6
|
const sessionnegotiator_ts_1 = require("../sessionnegotiator.js");
|
|
7
7
|
const throttler_ts_1 = require("../throttler.js");
|
|
8
|
+
const json_parser_ts_1 = require("./json-parser.js");
|
|
8
9
|
/**
|
|
9
10
|
* @remarks
|
|
10
11
|
* The TCP implementation has a known limitation where large command
|
|
@@ -108,8 +109,8 @@ class TCPHandle {
|
|
|
108
109
|
}
|
|
109
110
|
async connect(host, port, onConnected, onMessage) {
|
|
110
111
|
const { connect } = await Promise.resolve().then(() => require('node:net'));
|
|
111
|
-
const socket = connect({ host, port }).
|
|
112
|
-
let buffer =
|
|
112
|
+
const socket = connect({ host, port }).setKeepAlive(true);
|
|
113
|
+
let buffer = Buffer.alloc(0);
|
|
113
114
|
await new Promise((resolve) => {
|
|
114
115
|
socket.once('connect', () => {
|
|
115
116
|
resolve();
|
|
@@ -131,7 +132,7 @@ class TCPHandle {
|
|
|
131
132
|
}
|
|
132
133
|
});
|
|
133
134
|
socket.on('data', (chunk) => {
|
|
134
|
-
const result =
|
|
135
|
+
const result = (0, json_parser_ts_1.tryParseJSON)(buffer.length === 0 ? chunk : Buffer.concat([buffer, chunk]));
|
|
135
136
|
buffer = result.remainingBuffer;
|
|
136
137
|
for (const parsed of result.parsedObjects) {
|
|
137
138
|
onMessage(parsed);
|
|
@@ -142,56 +143,5 @@ class TCPHandle {
|
|
|
142
143
|
this.connectionAttempts = 0;
|
|
143
144
|
return socket;
|
|
144
145
|
}
|
|
145
|
-
tryParseJSON(buffer) {
|
|
146
|
-
const parsedObjects = [];
|
|
147
|
-
let currBuffer = buffer;
|
|
148
|
-
let startIndex = buffer.indexOf('{');
|
|
149
|
-
while (startIndex !== -1) {
|
|
150
|
-
let braceCount = 0;
|
|
151
|
-
let inString = false;
|
|
152
|
-
let escaped = false;
|
|
153
|
-
let foundEnd = false;
|
|
154
|
-
let endIndex = startIndex;
|
|
155
|
-
for (let i = startIndex; i < currBuffer.length; i++) {
|
|
156
|
-
const char = currBuffer[i];
|
|
157
|
-
if (inString) {
|
|
158
|
-
if (escaped) {
|
|
159
|
-
escaped = false;
|
|
160
|
-
}
|
|
161
|
-
else if (char === '\\') {
|
|
162
|
-
escaped = true;
|
|
163
|
-
}
|
|
164
|
-
else if (char === '"') {
|
|
165
|
-
inString = false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else if (char === '"') {
|
|
169
|
-
inString = true;
|
|
170
|
-
}
|
|
171
|
-
else if (char === '{') {
|
|
172
|
-
braceCount++;
|
|
173
|
-
}
|
|
174
|
-
else if (char === '}') {
|
|
175
|
-
braceCount--;
|
|
176
|
-
// When all opened braces are closed, we found the end.
|
|
177
|
-
if (braceCount === 0) {
|
|
178
|
-
endIndex = i;
|
|
179
|
-
foundEnd = true;
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
// If we haven't found a complete JSON object, break and wait for more data.
|
|
185
|
-
if (!foundEnd) {
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
const rawMessage = currBuffer.slice(startIndex, endIndex + 1).trim();
|
|
189
|
-
const parsed = JSON.parse(rawMessage);
|
|
190
|
-
parsedObjects.push(parsed);
|
|
191
|
-
currBuffer = currBuffer.slice(endIndex + 1);
|
|
192
|
-
startIndex = currBuffer.indexOf('{');
|
|
193
|
-
}
|
|
194
|
-
return { parsedObjects, remainingBuffer: currBuffer };
|
|
195
|
-
}
|
|
196
146
|
}
|
|
197
147
|
//# sourceMappingURL=tcpsender.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcpsender.js","sourceRoot":"","sources":["../../../../src/sender/tcp/tcpsender.ts"],"names":[],"mappings":";;;AAWA,kDAA2C;AAC3C,4CAAuG;AACvG,kEAA2D;AAC3D,kDAAmD;
|
|
1
|
+
{"version":3,"file":"tcpsender.js","sourceRoot":"","sources":["../../../../src/sender/tcp/tcpsender.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ export class EnvelopeResolver {
|
|
|
19
19
|
this.resolveEnvelopeResponse(id, new Error(`Envelope response timed out after ${timeoutSeconds} seconds`));
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
},
|
|
22
|
+
}, 5000);
|
|
23
23
|
}
|
|
24
24
|
async resolve(envelope) {
|
|
25
25
|
const deferred = this.waitingEnvelopeResponseResolvers[envelope.id];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function tryParseJSON(buffer) {
|
|
2
|
+
const parsedObjects = [];
|
|
3
|
+
let braceCount = 0;
|
|
4
|
+
let inString = false;
|
|
5
|
+
let escaped = false;
|
|
6
|
+
let objectStart = -1;
|
|
7
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
8
|
+
const ch = buffer[i];
|
|
9
|
+
if (inString) {
|
|
10
|
+
if (escaped) {
|
|
11
|
+
escaped = false;
|
|
12
|
+
// backslash '\'
|
|
13
|
+
}
|
|
14
|
+
else if (ch === 0x5c) {
|
|
15
|
+
escaped = true;
|
|
16
|
+
// double quote '"'
|
|
17
|
+
}
|
|
18
|
+
else if (ch === 0x22) {
|
|
19
|
+
inString = false;
|
|
20
|
+
}
|
|
21
|
+
// double quote '"'
|
|
22
|
+
}
|
|
23
|
+
else if (ch === 0x22) {
|
|
24
|
+
inString = true;
|
|
25
|
+
// opening brace '{'
|
|
26
|
+
}
|
|
27
|
+
else if (ch === 0x7b) {
|
|
28
|
+
if (braceCount === 0) {
|
|
29
|
+
objectStart = i;
|
|
30
|
+
}
|
|
31
|
+
braceCount++;
|
|
32
|
+
// closing brace '}'
|
|
33
|
+
}
|
|
34
|
+
else if (ch === 0x7d) {
|
|
35
|
+
braceCount--;
|
|
36
|
+
if (braceCount === 0 && objectStart !== -1) {
|
|
37
|
+
// full object from objectStart..i
|
|
38
|
+
parsedObjects.push(JSON.parse(buffer.subarray(objectStart, i + 1).toString('utf-8')));
|
|
39
|
+
objectStart = -1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// any leftover (partial) object
|
|
44
|
+
const remainingBuffer = objectStart >= 0 ? buffer.subarray(objectStart) : Buffer.alloc(0);
|
|
45
|
+
return { parsedObjects, remainingBuffer };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=json-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-parser.js","sourceRoot":"","sources":["../../../../src/sender/tcp/json-parser.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,YAAY,CAAI,MAA2B;IACvD,MAAM,aAAa,GAAa,EAAE,CAAA;IAClC,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,IAAI,WAAW,GAAG,CAAC,CAAC,CAAA;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QAEpB,IAAI,QAAQ,EAAE,CAAC;YACX,IAAI,OAAO,EAAE,CAAC;gBACV,OAAO,GAAG,KAAK,CAAA;gBACf,gBAAgB;YACpB,CAAC;iBAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,GAAG,IAAI,CAAA;gBACd,mBAAmB;YACvB,CAAC;iBAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACrB,QAAQ,GAAG,KAAK,CAAA;YACpB,CAAC;YACD,mBAAmB;QACvB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,QAAQ,GAAG,IAAI,CAAA;YACf,oBAAoB;QACxB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;gBACnB,WAAW,GAAG,CAAC,CAAA;YACnB,CAAC;YACD,UAAU,EAAE,CAAA;YACZ,oBAAoB;QACxB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,UAAU,EAAE,CAAA;YACZ,IAAI,UAAU,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzC,kCAAkC;gBAClC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAM,CAAC,CAAA;gBAC1F,WAAW,GAAG,CAAC,CAAC,CAAA;YACpB,CAAC;QACL,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,MAAM,eAAe,GAAG,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACzF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAA;AAC7C,CAAC"}
|
|
@@ -2,6 +2,7 @@ import { BlipError } from "../bliperror.js";
|
|
|
2
2
|
import { ConnectionSender, OpenConnectionSender } from "../sender.js";
|
|
3
3
|
import { SessionNegotiator } from "../sessionnegotiator.js";
|
|
4
4
|
import { EnvelopeThrottler } from "../throttler.js";
|
|
5
|
+
import { tryParseJSON } from "./json-parser.js";
|
|
5
6
|
/**
|
|
6
7
|
* @remarks
|
|
7
8
|
* The TCP implementation has a known limitation where large command
|
|
@@ -104,8 +105,8 @@ class TCPHandle {
|
|
|
104
105
|
}
|
|
105
106
|
async connect(host, port, onConnected, onMessage) {
|
|
106
107
|
const { connect } = await import('node:net');
|
|
107
|
-
const socket = connect({ host, port }).
|
|
108
|
-
let buffer =
|
|
108
|
+
const socket = connect({ host, port }).setKeepAlive(true);
|
|
109
|
+
let buffer = Buffer.alloc(0);
|
|
109
110
|
await new Promise((resolve) => {
|
|
110
111
|
socket.once('connect', () => {
|
|
111
112
|
resolve();
|
|
@@ -127,7 +128,7 @@ class TCPHandle {
|
|
|
127
128
|
}
|
|
128
129
|
});
|
|
129
130
|
socket.on('data', (chunk) => {
|
|
130
|
-
const result =
|
|
131
|
+
const result = tryParseJSON(buffer.length === 0 ? chunk : Buffer.concat([buffer, chunk]));
|
|
131
132
|
buffer = result.remainingBuffer;
|
|
132
133
|
for (const parsed of result.parsedObjects) {
|
|
133
134
|
onMessage(parsed);
|
|
@@ -138,56 +139,5 @@ class TCPHandle {
|
|
|
138
139
|
this.connectionAttempts = 0;
|
|
139
140
|
return socket;
|
|
140
141
|
}
|
|
141
|
-
tryParseJSON(buffer) {
|
|
142
|
-
const parsedObjects = [];
|
|
143
|
-
let currBuffer = buffer;
|
|
144
|
-
let startIndex = buffer.indexOf('{');
|
|
145
|
-
while (startIndex !== -1) {
|
|
146
|
-
let braceCount = 0;
|
|
147
|
-
let inString = false;
|
|
148
|
-
let escaped = false;
|
|
149
|
-
let foundEnd = false;
|
|
150
|
-
let endIndex = startIndex;
|
|
151
|
-
for (let i = startIndex; i < currBuffer.length; i++) {
|
|
152
|
-
const char = currBuffer[i];
|
|
153
|
-
if (inString) {
|
|
154
|
-
if (escaped) {
|
|
155
|
-
escaped = false;
|
|
156
|
-
}
|
|
157
|
-
else if (char === '\\') {
|
|
158
|
-
escaped = true;
|
|
159
|
-
}
|
|
160
|
-
else if (char === '"') {
|
|
161
|
-
inString = false;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
else if (char === '"') {
|
|
165
|
-
inString = true;
|
|
166
|
-
}
|
|
167
|
-
else if (char === '{') {
|
|
168
|
-
braceCount++;
|
|
169
|
-
}
|
|
170
|
-
else if (char === '}') {
|
|
171
|
-
braceCount--;
|
|
172
|
-
// When all opened braces are closed, we found the end.
|
|
173
|
-
if (braceCount === 0) {
|
|
174
|
-
endIndex = i;
|
|
175
|
-
foundEnd = true;
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// If we haven't found a complete JSON object, break and wait for more data.
|
|
181
|
-
if (!foundEnd) {
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
const rawMessage = currBuffer.slice(startIndex, endIndex + 1).trim();
|
|
185
|
-
const parsed = JSON.parse(rawMessage);
|
|
186
|
-
parsedObjects.push(parsed);
|
|
187
|
-
currBuffer = currBuffer.slice(endIndex + 1);
|
|
188
|
-
startIndex = currBuffer.indexOf('{');
|
|
189
|
-
}
|
|
190
|
-
return { parsedObjects, remainingBuffer: currBuffer };
|
|
191
|
-
}
|
|
192
142
|
}
|
|
193
143
|
//# sourceMappingURL=tcpsender.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcpsender.js","sourceRoot":"","sources":["../../../../src/sender/tcp/tcpsender.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAoC,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACvG,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"tcpsender.js","sourceRoot":"","sources":["../../../../src/sender/tcp/tcpsender.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-parser.d.ts","sourceRoot":"","sources":["../../../../src/sender/tcp/json-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe,CAAC,CAAC;IAC9B,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IACvB,eAAe,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;CACvC;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CA4C/E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcpsender.d.ts","sourceRoot":"","sources":["../../../../src/sender/tcp/tcpsender.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,OAAO,EACP,cAAc,EAGd,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACzB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAoB,KAAK,2BAA2B,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"tcpsender.d.ts","sourceRoot":"","sources":["../../../../src/sender/tcp/tcpsender.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,OAAO,EACP,cAAc,EAGd,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACzB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAoB,KAAK,2BAA2B,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAKvG;;;;;GAKG;AACH,qBAAa,SAAU,SAAQ,oBAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;gBAE1C,OAAO,EAAE,qBAAqB,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC;IAyB7D,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3D,WAAW,CAAC,IAAI,SAAS,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASnF,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BzD,mBAAmB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpE,KAAK;IAMlB,OAAc,KAAK;;;MAAoC;YAEzC,eAAe;CAahC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface ParseJSONResult<T> {
|
|
2
|
+
parsedObjects: Array<T>
|
|
3
|
+
remainingBuffer: Buffer<ArrayBuffer>
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function tryParseJSON<T>(buffer: Buffer<ArrayBuffer>): ParseJSONResult<T> {
|
|
7
|
+
const parsedObjects: Array<T> = []
|
|
8
|
+
let braceCount = 0
|
|
9
|
+
let inString = false
|
|
10
|
+
let escaped = false
|
|
11
|
+
|
|
12
|
+
let objectStart = -1
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
15
|
+
const ch = buffer[i]
|
|
16
|
+
|
|
17
|
+
if (inString) {
|
|
18
|
+
if (escaped) {
|
|
19
|
+
escaped = false
|
|
20
|
+
// backslash '\'
|
|
21
|
+
} else if (ch === 0x5c) {
|
|
22
|
+
escaped = true
|
|
23
|
+
// double quote '"'
|
|
24
|
+
} else if (ch === 0x22) {
|
|
25
|
+
inString = false
|
|
26
|
+
}
|
|
27
|
+
// double quote '"'
|
|
28
|
+
} else if (ch === 0x22) {
|
|
29
|
+
inString = true
|
|
30
|
+
// opening brace '{'
|
|
31
|
+
} else if (ch === 0x7b) {
|
|
32
|
+
if (braceCount === 0) {
|
|
33
|
+
objectStart = i
|
|
34
|
+
}
|
|
35
|
+
braceCount++
|
|
36
|
+
// closing brace '}'
|
|
37
|
+
} else if (ch === 0x7d) {
|
|
38
|
+
braceCount--
|
|
39
|
+
if (braceCount === 0 && objectStart !== -1) {
|
|
40
|
+
// full object from objectStart..i
|
|
41
|
+
parsedObjects.push(JSON.parse(buffer.subarray(objectStart, i + 1).toString('utf-8')) as T)
|
|
42
|
+
objectStart = -1
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// any leftover (partial) object
|
|
48
|
+
const remainingBuffer = objectStart >= 0 ? buffer.subarray(objectStart) : Buffer.alloc(0)
|
|
49
|
+
return { parsedObjects, remainingBuffer }
|
|
50
|
+
}
|
|
@@ -13,6 +13,7 @@ import { BlipError } from '../bliperror.ts'
|
|
|
13
13
|
import { ConnectionSender, type ConnectionSenderConstructor, OpenConnectionSender } from '../sender.ts'
|
|
14
14
|
import { SessionNegotiator } from '../sessionnegotiator.ts'
|
|
15
15
|
import { EnvelopeThrottler } from '../throttler.ts'
|
|
16
|
+
import { tryParseJSON } from './json-parser.ts'
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* @remarks
|
|
@@ -155,8 +156,8 @@ class TCPHandle<T> {
|
|
|
155
156
|
): Promise<Socket> {
|
|
156
157
|
const { connect } = await import('node:net')
|
|
157
158
|
|
|
158
|
-
const socket = connect({ host, port }).
|
|
159
|
-
let buffer =
|
|
159
|
+
const socket = connect({ host, port }).setKeepAlive(true)
|
|
160
|
+
let buffer = Buffer.alloc(0)
|
|
160
161
|
|
|
161
162
|
await new Promise<void>((resolve) => {
|
|
162
163
|
socket.once('connect', () => {
|
|
@@ -180,8 +181,8 @@ class TCPHandle<T> {
|
|
|
180
181
|
}
|
|
181
182
|
})
|
|
182
183
|
|
|
183
|
-
socket.on('data', (chunk) => {
|
|
184
|
-
const result =
|
|
184
|
+
socket.on('data', (chunk: Buffer<ArrayBuffer>) => {
|
|
185
|
+
const result = tryParseJSON<T>(buffer.length === 0 ? chunk : Buffer.concat([buffer, chunk]))
|
|
185
186
|
buffer = result.remainingBuffer
|
|
186
187
|
|
|
187
188
|
for (const parsed of result.parsedObjects) {
|
|
@@ -195,58 +196,4 @@ class TCPHandle<T> {
|
|
|
195
196
|
|
|
196
197
|
return socket
|
|
197
198
|
}
|
|
198
|
-
|
|
199
|
-
private tryParseJSON(buffer: string): { parsedObjects: Array<T>; remainingBuffer: string } {
|
|
200
|
-
const parsedObjects: Array<T> = []
|
|
201
|
-
let currBuffer = buffer
|
|
202
|
-
let startIndex = buffer.indexOf('{')
|
|
203
|
-
|
|
204
|
-
while (startIndex !== -1) {
|
|
205
|
-
let braceCount = 0
|
|
206
|
-
let inString = false
|
|
207
|
-
let escaped = false
|
|
208
|
-
let foundEnd = false
|
|
209
|
-
let endIndex = startIndex
|
|
210
|
-
|
|
211
|
-
for (let i = startIndex; i < currBuffer.length; i++) {
|
|
212
|
-
const char = currBuffer[i]
|
|
213
|
-
|
|
214
|
-
if (inString) {
|
|
215
|
-
if (escaped) {
|
|
216
|
-
escaped = false
|
|
217
|
-
} else if (char === '\\') {
|
|
218
|
-
escaped = true
|
|
219
|
-
} else if (char === '"') {
|
|
220
|
-
inString = false
|
|
221
|
-
}
|
|
222
|
-
} else if (char === '"') {
|
|
223
|
-
inString = true
|
|
224
|
-
} else if (char === '{') {
|
|
225
|
-
braceCount++
|
|
226
|
-
} else if (char === '}') {
|
|
227
|
-
braceCount--
|
|
228
|
-
// When all opened braces are closed, we found the end.
|
|
229
|
-
if (braceCount === 0) {
|
|
230
|
-
endIndex = i
|
|
231
|
-
foundEnd = true
|
|
232
|
-
break
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// If we haven't found a complete JSON object, break and wait for more data.
|
|
238
|
-
if (!foundEnd) {
|
|
239
|
-
break
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const rawMessage = currBuffer.slice(startIndex, endIndex + 1).trim()
|
|
243
|
-
const parsed = JSON.parse(rawMessage) as T
|
|
244
|
-
parsedObjects.push(parsed)
|
|
245
|
-
|
|
246
|
-
currBuffer = currBuffer.slice(endIndex + 1)
|
|
247
|
-
startIndex = currBuffer.indexOf('{')
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return { parsedObjects, remainingBuffer: currBuffer }
|
|
251
|
-
}
|
|
252
199
|
}
|