smoldot 3.6.0 → 3.7.0
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/internals/bytecode/wasm0.js +1 -1
- package/dist/cjs/internals/bytecode/wasm1.js +1 -1
- package/dist/cjs/internals/bytecode/wasm2.js +1 -1
- package/dist/cjs/internals/bytecode/wasm3.js +1 -1
- package/dist/cjs/internals/dns-over-https.d.ts +31 -0
- package/dist/cjs/internals/dns-over-https.js +255 -0
- package/dist/cjs/internals/local-instance.d.ts +7 -1
- package/dist/cjs/internals/local-instance.js +13 -3
- package/dist/cjs/no-auto-bytecode-browser.js +65 -13
- package/dist/mjs/internals/bytecode/wasm0.js +1 -1
- package/dist/mjs/internals/bytecode/wasm1.js +1 -1
- package/dist/mjs/internals/bytecode/wasm2.js +1 -1
- package/dist/mjs/internals/bytecode/wasm3.js +1 -1
- package/dist/mjs/internals/dns-over-https.d.ts +31 -0
- package/dist/mjs/internals/dns-over-https.js +249 -0
- package/dist/mjs/internals/local-instance.d.ts +7 -1
- package/dist/mjs/internals/local-instance.js +13 -3
- package/dist/mjs/no-auto-bytecode-browser.js +65 -13
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.startWithBytecode = exports.QueueFullError = exports.JsonRpcDisabledError = exports.CrashError = exports.AlreadyDestroyedError = exports.AddChainError = void 0;
|
|
16
16
|
const client_js_1 = require("./internals/client.js");
|
|
17
|
+
const dns_over_https_js_1 = require("./internals/dns-over-https.js");
|
|
17
18
|
var public_types_js_1 = require("./public-types.js");
|
|
18
19
|
Object.defineProperty(exports, "AddChainError", { enumerable: true, get: function () { return public_types_js_1.AddChainError; } });
|
|
19
20
|
Object.defineProperty(exports, "AlreadyDestroyedError", { enumerable: true, get: function () { return public_types_js_1.AlreadyDestroyedError; } });
|
|
@@ -194,17 +195,46 @@ function connect(config) {
|
|
|
194
195
|
openOutSubstream: () => { throw new Error('Connection is closed'); },
|
|
195
196
|
};
|
|
196
197
|
}
|
|
197
|
-
const { targetPort,
|
|
198
|
+
const { targetPort, remoteTlsCertificateSha256 } = config.address;
|
|
198
199
|
const state = {
|
|
199
200
|
pc: undefined,
|
|
200
201
|
dataChannels: new Map(),
|
|
201
202
|
nextStreamId: 0,
|
|
202
203
|
isFirstOutSubstream: true,
|
|
204
|
+
dnsAbort: null,
|
|
203
205
|
};
|
|
206
|
+
// The SDP answer needs the literal IP address of the remote.
|
|
207
|
+
// Browsers expose no DNS API, so a multiaddress with a domain name is resolved over
|
|
208
|
+
// DNS-over-HTTPS. Resolution is started here and is only awaited in
|
|
209
|
+
// `onnegotiationneeded`, where the IP is actually needed.
|
|
210
|
+
let target;
|
|
211
|
+
if ("targetIp" in config.address) {
|
|
212
|
+
target = Promise.resolve({ targetIp: config.address.targetIp, ipVersion: config.address.ipVersion });
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
const { hostname, family } = config.address;
|
|
216
|
+
const controller = new AbortController();
|
|
217
|
+
state.dnsAbort = controller;
|
|
218
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
219
|
+
const finished = () => {
|
|
220
|
+
clearTimeout(timeout);
|
|
221
|
+
state.dnsAbort = null;
|
|
222
|
+
};
|
|
223
|
+
target = (0, dns_over_https_js_1.resolveDnsOverHttps)(hostname, family, controller.signal).then((ip) => {
|
|
224
|
+
finished();
|
|
225
|
+
return { targetIp: ip, ipVersion: ip.includes(':') ? 6 : 4 };
|
|
226
|
+
}, (error) => {
|
|
227
|
+
finished();
|
|
228
|
+
throw error;
|
|
229
|
+
});
|
|
230
|
+
target.catch(() => { });
|
|
231
|
+
}
|
|
204
232
|
// Kills all the JavaScript objects (the connection and all its substreams), ensuring that no
|
|
205
233
|
// callback will be called again. Doesn't report anything to smoldot, as this should be done
|
|
206
234
|
// by the caller.
|
|
207
235
|
const killAllJs = () => {
|
|
236
|
+
if (state.dnsAbort)
|
|
237
|
+
state.dnsAbort.abort();
|
|
208
238
|
// The `RTCPeerConnection` is created pretty quickly. It is however still possible for
|
|
209
239
|
// smoldot to cancel the opening, in which case `pc` will still be undefined.
|
|
210
240
|
if (!state.pc) {
|
|
@@ -225,6 +255,18 @@ function connect(config) {
|
|
|
225
255
|
state.dataChannels.clear();
|
|
226
256
|
state.pc.close(); // Not necessarily necessary, but it doesn't hurt to do so.
|
|
227
257
|
};
|
|
258
|
+
// Due to <https://bugzilla.mozilla.org/show_bug.cgi?id=1659672>,
|
|
259
|
+
// connections from Firefox to a localhost WebRTC server always fail:
|
|
260
|
+
// Firefox gathers no loopback ICE candidate.
|
|
261
|
+
//
|
|
262
|
+
// Returns `true` if the connection was refused, in which case the caller must stop.
|
|
263
|
+
const refuseIfFirefoxLoopback = (ip) => {
|
|
264
|
+
if ((ip !== '127.0.0.1' && ip !== '::1') || navigator.userAgent.indexOf('Firefox') === -1)
|
|
265
|
+
return false;
|
|
266
|
+
killAllJs();
|
|
267
|
+
config.onConnectionReset("Firefox can't connect to a localhost WebRTC server");
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
228
270
|
// Function that configures a newly-opened channel and adds it to the map. Used for both
|
|
229
271
|
// inbound and outbound substreams.
|
|
230
272
|
const addChannel = (dataChannel, direction) => {
|
|
@@ -287,19 +329,10 @@ function connect(config) {
|
|
|
287
329
|
RTCPeerConnection.generateCertificate({ name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" }).then((localCertificate) => __awaiter(this, void 0, void 0, function* () {
|
|
288
330
|
if (state.pc === null)
|
|
289
331
|
return;
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
|
|
293
|
-
// term. In order to provider better user feedback, we straight up refuse connecting
|
|
294
|
-
// and stop the connection.
|
|
295
|
-
// Note that this is just a hint. Failing to detect this will lead to the WebRTC
|
|
296
|
-
// handshake timing out.
|
|
297
|
-
// TODO: eventually remove this if the Firefox bug is fixed
|
|
298
|
-
if ((targetIp == 'localhost' || targetIp == '127.0.0.1' || targetIp == '::1') && navigator.userAgent.indexOf('Firefox') !== -1) {
|
|
299
|
-
killAllJs();
|
|
300
|
-
config.onConnectionReset("Firefox can't connect to a localhost WebRTC server");
|
|
332
|
+
// A literal loopback address can be refused before anything is created. A domain
|
|
333
|
+
// name is checked once resolved, in `onnegotiationneeded`.
|
|
334
|
+
if ("targetIp" in config.address && refuseIfFirefoxLoopback(config.address.targetIp))
|
|
301
335
|
return;
|
|
302
|
-
}
|
|
303
336
|
// Create a new WebRTC connection.
|
|
304
337
|
state.pc = new RTCPeerConnection({ certificates: [localCertificate] });
|
|
305
338
|
// We need to build the multihash corresponding to the local certificate.
|
|
@@ -374,6 +407,25 @@ function connect(config) {
|
|
|
374
407
|
sdpOffer = sdpOffer.replace(/^a=ice-ufrag.*$/m, 'a=ice-ufrag:' + ufragPwd);
|
|
375
408
|
sdpOffer = sdpOffer.replace(/^a=ice-pwd.*$/m, 'a=ice-pwd:' + ufragPwd);
|
|
376
409
|
yield state.pc.setLocalDescription({ type: 'offer', sdp: sdpOffer });
|
|
410
|
+
// The answer needs the literal IP address of the remote, resolution was already stared.
|
|
411
|
+
let targetIp;
|
|
412
|
+
let ipVersion;
|
|
413
|
+
try {
|
|
414
|
+
({ targetIp, ipVersion } = yield target);
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
// `reset()` aborts the resolution, and a failure reported through
|
|
418
|
+
// `onconnectionstatechange` closes the connection.
|
|
419
|
+
if (state.pc.signalingState === "closed")
|
|
420
|
+
return;
|
|
421
|
+
killAllJs();
|
|
422
|
+
config.onConnectionReset("DNS resolution failed: " + (error instanceof Error ? error.message : String(error)));
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
if (state.pc.signalingState === "closed")
|
|
426
|
+
return;
|
|
427
|
+
if (refuseIfFirefoxLoopback(targetIp))
|
|
428
|
+
return;
|
|
377
429
|
// Transform certificate hash into fingerprint (upper-hex; each byte separated by ":").
|
|
378
430
|
const fingerprint = Array.from(remoteTlsCertificateSha256).map((n) => ("0" + n.toString(16)).slice(-2).toUpperCase()).join(':');
|
|
379
431
|
// Note that the trailing line feed is important, as otherwise Chrome
|