smoldot 2.0.10 → 2.0.11

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.
@@ -68,7 +68,7 @@ export interface Connection {
68
68
  *
69
69
  * Must not be called after `closeSend` has been called.
70
70
  */
71
- send(data: Uint8Array, streamId?: number): void;
71
+ send(data: Array<Uint8Array>, streamId?: number): void;
72
72
  /**
73
73
  * Closes the writing side of the given stream of the given connection.
74
74
  *
@@ -69,7 +69,7 @@ export type Event = {
69
69
  ty: "stream-send";
70
70
  connectionId: number;
71
71
  streamId?: number;
72
- data: Uint8Array;
72
+ data: Array<Uint8Array>;
73
73
  } | {
74
74
  ty: "stream-send-close";
75
75
  connectionId: number;
@@ -250,9 +250,15 @@ function startLocalInstance(config, wasmModule, eventCallback) {
250
250
  // that this function is called only when the connection is in an open state.
251
251
  stream_send: (connectionId, streamId, ptr, len) => {
252
252
  const instance = state.instance;
253
+ const mem = new Uint8Array(instance.exports.memory.buffer);
253
254
  ptr >>>= 0;
254
255
  len >>>= 0;
255
- const data = new Uint8Array(instance.exports.memory.buffer).slice(ptr, ptr + len);
256
+ const data = new Array();
257
+ for (let i = 0; i < len; ++i) {
258
+ const bufPtr = buffer.readUInt32LE(mem, ptr + 8 * i);
259
+ const bufLen = buffer.readUInt32LE(mem, ptr + 8 * i + 4);
260
+ data.push(mem.slice(bufPtr, bufPtr + bufLen));
261
+ }
256
262
  // TODO: docs says the streamId is provided only for multi-stream connections, but here it's always provided
257
263
  eventCallback({ ty: "stream-send", connectionId, streamId, data });
258
264
  },
@@ -29,6 +29,19 @@ Object.defineProperty(exports, "QueueFullError", { enumerable: true, get: functi
29
29
  */
30
30
  function startWithBytecode(options) {
31
31
  options.forbidTcp = true;
32
+ // When in a secure context, browsers refuse to open non-secure WebSocket connections to
33
+ // non-localhost. There is an exception if the page is localhost, in which case all connections
34
+ // are allowed.
35
+ // Detecting this ahead of time is better for the overall health of the client, as it will
36
+ // avoid storing in memory addresses that it knows it can't connect to.
37
+ // The condition below is a hint, and false-positives or false-negatives are not fundamentally
38
+ // an issue.
39
+ if ((typeof isSecureContext === 'boolean' && isSecureContext) && typeof location !== undefined) {
40
+ const loc = location.toString();
41
+ if (loc.indexOf('localhost') !== -1 && loc.indexOf('127.0.0.1') !== -1 && loc.indexOf('::1') !== -1) {
42
+ options.forbidNonLocalWs = true;
43
+ }
44
+ }
32
45
  return (0, client_js_1.start)(options, options.bytecode, {
33
46
  performanceNow: () => {
34
47
  return performance.now();
@@ -142,12 +155,14 @@ function connect(config) {
142
155
  connection = null;
143
156
  },
144
157
  send: (data) => {
145
- connection.send(data);
146
158
  if (bufferedAmountCheck.quenedUnreportedBytes == 0) {
147
159
  bufferedAmountCheck.nextTimeout = 10;
148
160
  setTimeout(checkBufferedAmount, 10);
149
161
  }
150
- bufferedAmountCheck.quenedUnreportedBytes += data.length;
162
+ for (const buffer of data) {
163
+ bufferedAmountCheck.quenedUnreportedBytes += buffer.length;
164
+ }
165
+ connection.send(new Blob(data));
151
166
  },
152
167
  closeSend: () => { throw new Error('Wrong connection type'); },
153
168
  openOutSubstream: () => { throw new Error('Wrong connection type'); }
@@ -418,8 +433,10 @@ function connect(config) {
418
433
  },
419
434
  send: (data, streamId) => {
420
435
  const channel = state.dataChannels.get(streamId);
421
- channel.channel.send(data);
422
- channel.bufferedBytes += data.length;
436
+ for (const buffer of data) {
437
+ channel.bufferedBytes += buffer.length;
438
+ }
439
+ channel.channel.send(new Blob(data));
423
440
  },
424
441
  closeSend: () => { throw new Error('Wrong connection type'); },
425
442
  openOutSubstream: () => {
@@ -105,12 +105,14 @@ function connect(config) {
105
105
  // we thus absorb any exception thrown here.
106
106
  // See also <https://github.com/paritytech/smoldot/issues/2937>.
107
107
  try {
108
- socket.send(data);
109
108
  if (bufferedAmountCheck.quenedUnreportedBytes == 0) {
110
109
  bufferedAmountCheck.nextTimeout = 10;
111
110
  setTimeout(checkBufferedAmount, 10);
112
111
  }
113
- bufferedAmountCheck.quenedUnreportedBytes += data.length;
112
+ for (const buffer of data) {
113
+ bufferedAmountCheck.quenedUnreportedBytes += buffer.length;
114
+ }
115
+ socket.send(new Blob(data));
114
116
  }
115
117
  catch (_error) { }
116
118
  },
@@ -172,31 +174,35 @@ function connect(config) {
172
174
  socket.inner.then((connec) => connec.close());
173
175
  },
174
176
  send: (data) => {
175
- let dataCopy = Uint8Array.from(data); // Deep copy of the data
177
+ let dataCopy = data.map((buf) => Uint8Array.from(buf)); // Deep copy of the data
176
178
  socket.inner = socket.inner.then((c) => __awaiter(this, void 0, void 0, function* () {
177
- while (dataCopy.length > 0) {
178
- if (socket.destroyed || c === null)
179
- return c;
180
- let outcome;
181
- try {
182
- outcome = yield c.write(dataCopy);
183
- config.onWritableBytes(dataCopy.length);
184
- }
185
- catch (error) {
186
- // The type of `error` is unclear, but we assume that it implements `Error`
187
- outcome = error.toString();
188
- }
189
- if (typeof outcome !== 'number') {
190
- // The socket is reported closed, but `socket.destroyed` is still
191
- // `false` (see check above). As such, we must inform the inner layers.
192
- socket.destroyed = true;
193
- config.onConnectionReset(outcome);
194
- return c;
179
+ for (let buffer of dataCopy) {
180
+ while (buffer.length > 0) {
181
+ if (socket.destroyed || c === null)
182
+ return c;
183
+ let outcome;
184
+ try {
185
+ outcome = yield c.write(buffer);
186
+ config.onWritableBytes(buffer.length);
187
+ }
188
+ catch (error) {
189
+ // The type of `error` is unclear, but we assume that it
190
+ // implements `Error`
191
+ outcome = error.toString();
192
+ }
193
+ if (typeof outcome !== 'number') {
194
+ // The socket is reported closed, but `socket.destroyed` is still
195
+ // `false` (see check above). As such, we must inform the
196
+ // inner layers.
197
+ socket.destroyed = true;
198
+ config.onConnectionReset(outcome);
199
+ return c;
200
+ }
201
+ // Note that, contrary to `read`, it is possible for `outcome` to be 0.
202
+ // This happen if the write had to be interrupted, and the only thing
203
+ // we have to do is try writing again.
204
+ buffer = buffer.slice(outcome);
195
205
  }
196
- // Note that, contrary to `read`, it is possible for `outcome` to be 0.
197
- // This happen if the write had to be interrupted, and the only thing
198
- // we have to do is try writing again.
199
- dataCopy = dataCopy.slice(outcome);
200
206
  }
201
207
  return c;
202
208
  }));
@@ -106,12 +106,14 @@ function connect(config) {
106
106
  socket.close();
107
107
  },
108
108
  send: (data) => {
109
- socket.send(data);
110
109
  if (bufferedAmountCheck.quenedUnreportedBytes == 0) {
111
110
  bufferedAmountCheck.nextTimeout = 10;
112
111
  setTimeout(checkBufferedAmount, 10);
113
112
  }
114
- bufferedAmountCheck.quenedUnreportedBytes += data.length;
113
+ for (const buffer of data) {
114
+ socket.send(buffer);
115
+ bufferedAmountCheck.quenedUnreportedBytes += buffer.length;
116
+ }
115
117
  },
116
118
  closeSend: () => { throw new Error('Wrong connection type'); },
117
119
  openOutSubstream: () => { throw new Error('Wrong connection type'); }
@@ -158,17 +160,19 @@ function connect(config) {
158
160
  socket.destroy();
159
161
  },
160
162
  send: (data) => {
161
- const dataLen = data.length;
162
- const allWritten = socket.write(data);
163
- if (allWritten) {
164
- setImmediate(() => {
165
- if (!socket.writable)
166
- return;
167
- config.onWritableBytes(dataLen);
168
- });
169
- }
170
- else {
171
- drainingBytes.num += dataLen;
163
+ for (const buffer of data) {
164
+ const bufferLen = buffer.length;
165
+ const allWritten = socket.write(buffer);
166
+ if (allWritten) {
167
+ setImmediate(() => {
168
+ if (!socket.writable)
169
+ return;
170
+ config.onWritableBytes(bufferLen);
171
+ });
172
+ }
173
+ else {
174
+ drainingBytes.num += bufferLen;
175
+ }
172
176
  }
173
177
  },
174
178
  closeSend: () => {