Skip to content

Commit e738efe

Browse files
michaelsbradleyjr0x-r4bbit
authored andcommitted
refactor(@embark/blockchain_process): swallow errors, revise streams
For reasons unknown, `ECONNRESET` errors on websocket connections to embark's blockchain proxy are not automatically handled on Windows as they are on macOS and Linux (or those errors aren't happening on those platforms, it's difficult to determine). Explicitly swallow such errors so the blockchain process doesn't crash. Prior to this PR, the crash-behavior can be reproduced on Windows by running `embark blockchain` and `embark run` in separate terminals and quitting `embark run` while `embark blockchain` is still running. Consistently use the `simples` package's `WsParser` to process websocket traffic instead of using `WsParser` for requests and the `ws` package's `Websocket.Receiver` for responses. Consistently use `pump` to connect parser streams instead of using `pump` in some places and `chain` in others. Drop use of `cloneable` (and the package dependency) since it was used previously in hopes it would fix the errors, but it's unnecessary and didn't fix them.
1 parent 7d2ceaa commit e738efe

File tree

3 files changed

+21
-42
lines changed

3 files changed

+21
-42
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191
"chokidar": "2.0.4",
9292
"clipboardy": "1.2.3",
9393
"clone-deep": "4.0.0",
94-
"cloneable-readable": "2.0.0",
9594
"colors": "1.3.2",
9695
"commander": "2.18.0",
9796
"css-loader": "1.0.0",

src/lib/modules/blockchain_process/proxy.js

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@
22

33
const Asm = require('stream-json/Assembler');
44
const {canonicalHost, defaultHost} = require('../../utils/host');
5-
const {chain} = require('stream-chain');
6-
const cloneable = require('cloneable-readable');
75
const constants = require('../../constants.json');
86
const express = require('express');
9-
const {parser} = require('stream-json');
7+
const {parser: jsonParser} = require('stream-json');
108
const proxyMiddleware = require('http-proxy-middleware');
119
const pump = require('pump');
1210
const utils = require('../../utils/utils');
13-
const WebSocket = require('ws');
1411
const WsParser = require('simples/lib/parsers/ws');
1512

1613
const hex = (n) => {
@@ -21,17 +18,17 @@ const hex = (n) => {
2118
const parseJsonMaybe = (string) => {
2219
let object;
2320
if (typeof string === 'string') {
21+
// ignore empty strings
2422
if (string) {
2523
try {
2624
object = JSON.parse(string);
2725
} catch(e) {
26+
// ignore client/server byte sequences sent when connections are closing
2827
if (Array.from(Buffer.from(string)).map(hex).join(':') !==
2928
'03:ef:bf:bd') {
3029
console.error(`Proxy: Error parsing string as JSON '${string}'`);
3130
}
3231
}
33-
} else {
34-
console.error('Proxy: Expected a non-empty string');
3532
}
3633
} else {
3734
console.error(`Proxy: Expected a string but got type '${typeof string}'`);
@@ -137,10 +134,9 @@ exports.serve = async (ipc, host, port, ws, origin) => {
137134
onProxyReq(_proxyReq, req, _res) {
138135
if (req.method === 'POST') {
139136
// messages TO the target
140-
Asm.connectTo(chain([
141-
req,
142-
parser()
143-
])).on('done', ({current: object}) => {
137+
Asm.connectTo(
138+
pump(req, jsonParser())
139+
).on('done', ({current: object}) => {
144140
trackRequest(object);
145141
});
146142
}
@@ -149,10 +145,9 @@ exports.serve = async (ipc, host, port, ws, origin) => {
149145
onProxyRes(proxyRes, req, _res) {
150146
if (req.method === 'POST') {
151147
// messages FROM the target
152-
Asm.connectTo(chain([
153-
proxyRes,
154-
parser()
155-
])).on('done', ({current: object}) => {
148+
Asm.connectTo(
149+
pump(proxyRes, jsonParser())
150+
).on('done', ({current: object}) => {
156151
trackResponse(object);
157152
});
158153
}
@@ -162,22 +157,18 @@ exports.serve = async (ipc, host, port, ws, origin) => {
162157
if (ws) {
163158
proxyOpts.onProxyReqWs = (_proxyReq, _req, socket, _options, _head) => {
164159
// messages TO the target
165-
const wsp = new WsParser(0, false);
166-
wsp.on('frame', ({data: buffer}) => {
160+
pump(socket, new WsParser(0, false)).on('frame', ({data: buffer}) => {
167161
const object = parseJsonMaybe(buffer.toString());
168162
trackRequest(object);
169163
});
170-
pump(cloneable(socket), wsp);
171164
};
172165

173166
proxyOpts.onOpen = (proxySocket) => {
174167
// messages FROM the target
175-
const recv = new WebSocket.Receiver();
176-
recv.on('message', (data) => {
177-
const object = parseJsonMaybe(data);
168+
pump(proxySocket, new WsParser(0, true)).on('frame', ({data: buffer}) => {
169+
const object = parseJsonMaybe(buffer.toString());
178170
trackResponse(object);
179171
});
180-
pump(cloneable(proxySocket), recv);
181172
};
182173
}
183174

@@ -192,7 +183,13 @@ exports.serve = async (ipc, host, port, ws, origin) => {
192183
() => { resolve(server); }
193184
);
194185
if (ws) {
195-
server.on('upgrade', proxy.upgrade);
186+
server.on('upgrade', (msg, socket, head) => {
187+
const swallowError = (err) => {
188+
console.error(`Proxy: Network error '${err.message}'`);
189+
};
190+
socket.on('error', swallowError);
191+
proxy.upgrade(msg, socket, head);
192+
});
196193
}
197194
});
198195
};

yarn.lock

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,14 +2333,6 @@ clone@^1.0.2:
23332333
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
23342334
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
23352335

2336-
cloneable-readable@2.0.0:
2337-
version "2.0.0"
2338-
resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-2.0.0.tgz#57b05f40f0dc95f5d6e18992c845f5fcf5b24f51"
2339-
integrity sha512-YjptvQM0hnSgrEQJPnGu3MqaK3iZ+37HaVBf5/wHyViQUQOGz5w+C44DllnInlUQjDISTyErf4Xa+RFEF1QB3Q==
2340-
dependencies:
2341-
inherits "^2.0.1"
2342-
readable-stream "^3.0.0"
2343-
23442336
co@^4.6.0:
23452337
version "4.6.0"
23462338
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -8175,15 +8167,6 @@ readable-stream@^1.0.33:
81758167
isarray "0.0.1"
81768168
string_decoder "~0.10.x"
81778169

8178-
readable-stream@^3.0.0:
8179-
version "3.0.6"
8180-
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.0.6.tgz#351302e4c68b5abd6a2ed55376a7f9a25be3057a"
8181-
integrity sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==
8182-
dependencies:
8183-
inherits "^2.0.3"
8184-
string_decoder "^1.1.1"
8185-
util-deprecate "^1.0.1"
8186-
81878170
readable-stream@~1.0.15:
81888171
version "1.0.34"
81898172
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
@@ -9389,7 +9372,7 @@ string.prototype.padend@^3.0.0:
93899372
es-abstract "^1.4.3"
93909373
function-bind "^1.0.2"
93919374

9392-
string_decoder@^1.0.0, string_decoder@^1.1.1:
9375+
string_decoder@^1.0.0:
93939376
version "1.2.0"
93949377
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
93959378
integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
@@ -10142,7 +10125,7 @@ utf8@^2.1.1:
1014210125
resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96"
1014310126
integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=
1014410127

10145-
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
10128+
util-deprecate@~1.0.1:
1014610129
version "1.0.2"
1014710130
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
1014810131
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=

0 commit comments

Comments
 (0)