@bytecodealliance/preview2-shim 0.17.8 → 0.17.9

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.
@@ -1,27 +1,27 @@
1
- import { createSocket } from 'node:dgram';
1
+ import { createSocket } from "node:dgram";
2
2
  import {
3
- createFuture,
4
- futureDispose,
5
- futureTakeValue,
6
- pollStateReady,
7
- verifyPollsDroppedForDrop,
8
- } from './worker-thread.js';
3
+ createFuture,
4
+ futureDispose,
5
+ futureTakeValue,
6
+ pollStateReady,
7
+ verifyPollsDroppedForDrop,
8
+ } from "./worker-thread.js";
9
9
  import {
10
- convertSocketError,
11
- convertSocketErrorCode,
12
- getDefaultReceiveBufferSize,
13
- getDefaultSendBufferSize,
14
- ipSocketAddress,
15
- isIPv4MappedAddress,
16
- isWildcardAddress,
17
- noLookup,
18
- serializeIpAddress,
19
- SOCKET_STATE_BIND,
20
- SOCKET_STATE_BOUND,
21
- SOCKET_STATE_CLOSED,
22
- SOCKET_STATE_CONNECTION,
23
- SOCKET_STATE_INIT,
24
- } from './worker-sockets.js';
10
+ convertSocketError,
11
+ convertSocketErrorCode,
12
+ getDefaultReceiveBufferSize,
13
+ getDefaultSendBufferSize,
14
+ ipSocketAddress,
15
+ isIPv4MappedAddress,
16
+ isWildcardAddress,
17
+ noLookup,
18
+ serializeIpAddress,
19
+ SOCKET_STATE_BIND,
20
+ SOCKET_STATE_BOUND,
21
+ SOCKET_STATE_CLOSED,
22
+ SOCKET_STATE_CONNECTION,
23
+ SOCKET_STATE_INIT,
24
+ } from "./worker-sockets.js";
25
25
 
26
26
  // Experimental support for batched UDP sends. Set this to true to enable.
27
27
  // This is not enabled by default because we need to figure out how to know
@@ -61,7 +61,7 @@ const UDP_BATCH_SENDS = false;
61
61
  */
62
62
 
63
63
  let udpSocketCnt = 0,
64
- datagramStreamCnt = 0;
64
+ datagramStreamCnt = 0;
65
65
 
66
66
  /**
67
67
  * @type {Map<number, UdpSocketRecord>}
@@ -78,32 +78,32 @@ export const datagramStreams = new Map();
78
78
  * @returns {number}
79
79
  */
80
80
  export function createUdpSocket({ family, unicastHopLimit }) {
81
- const udpSocket = createSocket({
82
- type: family === 'ipv6' ? 'udp6' : 'udp4',
83
- reuseAddr: false,
84
- ipv6Only: family === 'ipv6',
85
- lookup: noLookup,
86
- });
87
- udpSockets.set(++udpSocketCnt, {
88
- state: SOCKET_STATE_INIT,
89
- remoteAddress: null,
90
- remotePort: null,
91
- sendBufferSize: null,
92
- receiveBufferSize: null,
93
- unicastHopLimit,
94
- udpSocket,
95
- future: null,
96
- serializedLocalAddress: null,
97
- pollState: {
98
- ready: true,
99
- listener: null,
100
- polls: [],
101
- parentStream: null,
102
- },
103
- incomingDatagramStream: null,
104
- outgoingDatagramStream: null,
105
- });
106
- return udpSocketCnt;
81
+ const udpSocket = createSocket({
82
+ type: family === "ipv6" ? "udp6" : "udp4",
83
+ reuseAddr: false,
84
+ ipv6Only: family === "ipv6",
85
+ lookup: noLookup,
86
+ });
87
+ udpSockets.set(++udpSocketCnt, {
88
+ state: SOCKET_STATE_INIT,
89
+ remoteAddress: null,
90
+ remotePort: null,
91
+ sendBufferSize: null,
92
+ receiveBufferSize: null,
93
+ unicastHopLimit,
94
+ udpSocket,
95
+ future: null,
96
+ serializedLocalAddress: null,
97
+ pollState: {
98
+ ready: true,
99
+ listener: null,
100
+ polls: [],
101
+ parentStream: null,
102
+ },
103
+ incomingDatagramStream: null,
104
+ outgoingDatagramStream: null,
105
+ });
106
+ return udpSocketCnt;
107
107
  }
108
108
 
109
109
  /**
@@ -111,45 +111,45 @@ export function createUdpSocket({ family, unicastHopLimit }) {
111
111
  * @returns {DatagramStreamRecord}
112
112
  */
113
113
  function createIncomingDatagramStream(socket) {
114
- const id = ++datagramStreamCnt;
115
- const pollState = {
116
- ready: false,
117
- listener: null,
118
- polls: [],
119
- parentStream: null,
120
- };
121
- const datagramStream = {
122
- id,
123
- active: true,
124
- error: null,
125
- socket,
126
- queue: [],
127
- cleanup,
128
- pollState,
129
- };
130
- const { udpSocket } = socket;
131
- datagramStreams.set(id, datagramStream);
132
- function cleanup() {
133
- udpSocket.off('message', onMessage);
134
- udpSocket.off('error', onError);
135
- }
136
- function onMessage(data, rinfo) {
137
- const family = rinfo.family.toLowerCase();
138
- datagramStream.queue.push({
139
- data,
140
- remoteAddress: ipSocketAddress(family, rinfo.address, rinfo.port),
141
- });
142
- if (!pollState.ready) {
143
- pollStateReady(pollState);
144
- }
145
- }
146
- function onError(err) {
147
- datagramStream.error = err;
148
- pollStateReady(datagramStream.pollState);
149
- }
150
- udpSocket.on('message', onMessage);
151
- udpSocket.once('error', onError);
152
- return datagramStream;
114
+ const id = ++datagramStreamCnt;
115
+ const pollState = {
116
+ ready: false,
117
+ listener: null,
118
+ polls: [],
119
+ parentStream: null,
120
+ };
121
+ const datagramStream = {
122
+ id,
123
+ active: true,
124
+ error: null,
125
+ socket,
126
+ queue: [],
127
+ cleanup,
128
+ pollState,
129
+ };
130
+ const { udpSocket } = socket;
131
+ datagramStreams.set(id, datagramStream);
132
+ function cleanup() {
133
+ udpSocket.off("message", onMessage);
134
+ udpSocket.off("error", onError);
135
+ }
136
+ function onMessage(data, rinfo) {
137
+ const family = rinfo.family.toLowerCase();
138
+ datagramStream.queue.push({
139
+ data,
140
+ remoteAddress: ipSocketAddress(family, rinfo.address, rinfo.port),
141
+ });
142
+ if (!pollState.ready) {
143
+ pollStateReady(pollState);
144
+ }
145
+ }
146
+ function onError(err) {
147
+ datagramStream.error = err;
148
+ pollStateReady(datagramStream.pollState);
149
+ }
150
+ udpSocket.on("message", onMessage);
151
+ udpSocket.once("error", onError);
152
+ return datagramStream;
153
153
  }
154
154
 
155
155
  /**
@@ -157,92 +157,92 @@ function createIncomingDatagramStream(socket) {
157
157
  * @returns {DatagramStreamRecord}
158
158
  */
159
159
  function createOutgoingDatagramStream(socket) {
160
- const id = ++datagramStreamCnt;
161
- const datagramStream = {
162
- id,
163
- active: true,
164
- error: null,
165
- socket,
166
- cleanup,
167
- pollState: {
168
- ready: true,
169
- listener: null,
170
- polls: [],
171
- parentStream: null,
172
- },
173
- };
174
- const { udpSocket } = socket;
175
- datagramStreams.set(id, datagramStream);
176
- udpSocket.on('error', onError);
177
- function onError(err) {
178
- datagramStream.error = err;
179
- pollStateReady(datagramStream.pollState);
180
- }
181
- function cleanup() {
182
- udpSocket.off('error', onError);
183
- }
184
- return datagramStream;
160
+ const id = ++datagramStreamCnt;
161
+ const datagramStream = {
162
+ id,
163
+ active: true,
164
+ error: null,
165
+ socket,
166
+ cleanup,
167
+ pollState: {
168
+ ready: true,
169
+ listener: null,
170
+ polls: [],
171
+ parentStream: null,
172
+ },
173
+ };
174
+ const { udpSocket } = socket;
175
+ datagramStreams.set(id, datagramStream);
176
+ udpSocket.on("error", onError);
177
+ function onError(err) {
178
+ datagramStream.error = err;
179
+ pollStateReady(datagramStream.pollState);
180
+ }
181
+ function cleanup() {
182
+ udpSocket.off("error", onError);
183
+ }
184
+ return datagramStream;
185
185
  }
186
186
 
187
187
  export function socketUdpBindStart(id, localAddress, family) {
188
- const socket = udpSockets.get(id);
189
-
190
- if (family !== localAddress.tag || isIPv4MappedAddress(localAddress)) {
191
- throw 'invalid-argument';
192
- }
193
-
194
- const serializedLocalAddress = serializeIpAddress(localAddress);
195
-
196
- if (socket.state !== SOCKET_STATE_INIT) {
197
- throw 'invalid-state';
198
- }
199
- socket.state = SOCKET_STATE_BIND;
200
- const { udpSocket } = socket;
201
- socket.future = createFuture(
202
- new Promise((resolve, reject) => {
203
- function bindOk() {
204
- resolve();
205
- udpSocket.off('error', bindErr);
206
- }
207
- function bindErr(err) {
208
- reject(convertSocketError(err));
209
- udpSocket.off('listening', bindOk);
210
- }
211
- udpSocket.once('listening', bindOk);
212
- udpSocket.once('error', bindErr);
213
- udpSocket.bind(localAddress.val.port, serializedLocalAddress);
214
- }),
215
- socket.pollState
216
- );
188
+ const socket = udpSockets.get(id);
189
+
190
+ if (family !== localAddress.tag || isIPv4MappedAddress(localAddress)) {
191
+ throw "invalid-argument";
192
+ }
193
+
194
+ const serializedLocalAddress = serializeIpAddress(localAddress);
195
+
196
+ if (socket.state !== SOCKET_STATE_INIT) {
197
+ throw "invalid-state";
198
+ }
199
+ socket.state = SOCKET_STATE_BIND;
200
+ const { udpSocket } = socket;
201
+ socket.future = createFuture(
202
+ new Promise((resolve, reject) => {
203
+ function bindOk() {
204
+ resolve();
205
+ udpSocket.off("error", bindErr);
206
+ }
207
+ function bindErr(err) {
208
+ reject(convertSocketError(err));
209
+ udpSocket.off("listening", bindOk);
210
+ }
211
+ udpSocket.once("listening", bindOk);
212
+ udpSocket.once("error", bindErr);
213
+ udpSocket.bind(localAddress.val.port, serializedLocalAddress);
214
+ }),
215
+ socket.pollState,
216
+ );
217
217
  }
218
218
 
219
219
  export function socketUdpBindFinish(id) {
220
- const socket = udpSockets.get(id);
221
- if (socket.state !== SOCKET_STATE_BIND) {
222
- throw 'not-in-progress';
223
- }
224
- if (!socket.pollState.ready) {
225
- throw 'would-block';
220
+ const socket = udpSockets.get(id);
221
+ if (socket.state !== SOCKET_STATE_BIND) {
222
+ throw "not-in-progress";
223
+ }
224
+ if (!socket.pollState.ready) {
225
+ throw "would-block";
226
+ }
227
+ const { tag, val } = futureTakeValue(socket.future).val;
228
+ futureDispose(socket.future, false);
229
+ socket.future = null;
230
+ if (tag === "err") {
231
+ socket.state = SOCKET_STATE_CLOSED;
232
+ throw val;
233
+ } else {
234
+ // once bound, we can now set the options
235
+ // since Node.js doesn't support setting them until bound
236
+ socket.udpSocket.setTTL(socket.unicastHopLimit);
237
+ if (socket.sendBufferSize) {
238
+ socket.udpSocket.setRecvBufferSize(socket.sendBufferSize);
226
239
  }
227
- const { tag, val } = futureTakeValue(socket.future).val;
228
- futureDispose(socket.future, false);
229
- socket.future = null;
230
- if (tag === 'err') {
231
- socket.state = SOCKET_STATE_CLOSED;
232
- throw val;
233
- } else {
234
- // once bound, we can now set the options
235
- // since Node.js doesn't support setting them until bound
236
- socket.udpSocket.setTTL(socket.unicastHopLimit);
237
- if (socket.sendBufferSize) {
238
- socket.udpSocket.setRecvBufferSize(socket.sendBufferSize);
239
- }
240
- if (socket.receieveBufferSize) {
241
- socket.udpSocket.setSendBufferSize(socket.receiveBufferSize);
242
- }
243
- socket.state = SOCKET_STATE_BOUND;
244
- return val;
240
+ if (socket.receieveBufferSize) {
241
+ socket.udpSocket.setSendBufferSize(socket.receiveBufferSize);
245
242
  }
243
+ socket.state = SOCKET_STATE_BOUND;
244
+ return val;
245
+ }
246
246
  }
247
247
 
248
248
  /**
@@ -250,14 +250,14 @@ export function socketUdpBindFinish(id) {
250
250
  * @returns {IpSocketAddress}
251
251
  */
252
252
  export function socketUdpGetLocalAddress(id) {
253
- const { udpSocket } = udpSockets.get(id);
254
- let address, family, port;
255
- try {
256
- ({ address, family, port } = udpSocket.address());
257
- } catch (err) {
258
- throw convertSocketError(err);
259
- }
260
- return ipSocketAddress(family.toLowerCase(), address, port);
253
+ const { udpSocket } = udpSockets.get(id);
254
+ let address, family, port;
255
+ try {
256
+ ({ address, family, port } = udpSocket.address());
257
+ } catch (err) {
258
+ throw convertSocketError(err);
259
+ }
260
+ return ipSocketAddress(family.toLowerCase(), address, port);
261
261
  }
262
262
 
263
263
  /**
@@ -265,377 +265,323 @@ export function socketUdpGetLocalAddress(id) {
265
265
  * @returns {IpSocketAddress}
266
266
  */
267
267
  export function socketUdpGetRemoteAddress(id) {
268
- const { udpSocket } = udpSockets.get(id);
269
- let address, family, port;
270
- try {
271
- ({ address, family, port } = udpSocket.remoteAddress());
272
- } catch (err) {
273
- throw convertSocketError(err);
274
- }
275
- return ipSocketAddress(family.toLowerCase(), address, port);
268
+ const { udpSocket } = udpSockets.get(id);
269
+ let address, family, port;
270
+ try {
271
+ ({ address, family, port } = udpSocket.remoteAddress());
272
+ } catch (err) {
273
+ throw convertSocketError(err);
274
+ }
275
+ return ipSocketAddress(family.toLowerCase(), address, port);
276
276
  }
277
277
 
278
278
  export function socketUdpStream(id, remoteAddress) {
279
- const socket = udpSockets.get(id);
280
- const { udpSocket } = socket;
281
-
282
- if (
283
- socket.state !== SOCKET_STATE_BOUND &&
284
- socket.state !== SOCKET_STATE_CONNECTION
285
- ) {
286
- throw 'invalid-state';
287
- }
288
-
289
- if (socket.state === SOCKET_STATE_INIT && !remoteAddress) {
290
- throw 'invalid-state';
291
- }
292
-
293
- if (
294
- remoteAddress &&
295
- (remoteAddress.val.port === 0 ||
296
- isWildcardAddress(remoteAddress) ||
297
- (remoteAddress.tag === 'ipv6' &&
298
- isIPv4MappedAddress(remoteAddress)))
299
- ) {
300
- throw 'invalid-argument';
301
- }
302
-
303
- if (socket.state === SOCKET_STATE_CONNECTION) {
304
- socketDatagramStreamClear(socket.incomingDatagramStream);
305
- socketDatagramStreamClear(socket.outgoingDatagramStream);
306
- try {
307
- udpSocket.disconnect();
308
- } catch (e) {
309
- throw convertSocketErrorCode(e);
279
+ const socket = udpSockets.get(id);
280
+ const { udpSocket } = socket;
281
+
282
+ if (socket.state !== SOCKET_STATE_BOUND && socket.state !== SOCKET_STATE_CONNECTION) {
283
+ throw "invalid-state";
284
+ }
285
+
286
+ if (socket.state === SOCKET_STATE_INIT && !remoteAddress) {
287
+ throw "invalid-state";
288
+ }
289
+
290
+ if (
291
+ remoteAddress &&
292
+ (remoteAddress.val.port === 0 ||
293
+ isWildcardAddress(remoteAddress) ||
294
+ (remoteAddress.tag === "ipv6" && isIPv4MappedAddress(remoteAddress)))
295
+ ) {
296
+ throw "invalid-argument";
297
+ }
298
+
299
+ if (socket.state === SOCKET_STATE_CONNECTION) {
300
+ socketDatagramStreamClear(socket.incomingDatagramStream);
301
+ socketDatagramStreamClear(socket.outgoingDatagramStream);
302
+ try {
303
+ udpSocket.disconnect();
304
+ } catch (e) {
305
+ throw convertSocketErrorCode(e);
306
+ }
307
+ }
308
+
309
+ if (remoteAddress) {
310
+ const serializedRemoteAddress = serializeIpAddress(remoteAddress);
311
+ socket.remoteAddress = serializedRemoteAddress;
312
+ socket.remotePort = remoteAddress.val.port;
313
+ return new Promise((resolve, reject) => {
314
+ function connectOk() {
315
+ if (socket.state === SOCKET_STATE_INIT) {
316
+ socket.udpSocket.setTTL(socket.unicastHopLimit);
317
+ socket.udpSocket.setRecvBufferSize(socket.sendBufferSize);
318
+ socket.udpSocket.setSendBufferSize(socket.receiveBufferSize);
310
319
  }
311
- }
312
-
313
- if (remoteAddress) {
314
- const serializedRemoteAddress = serializeIpAddress(remoteAddress);
315
- socket.remoteAddress = serializedRemoteAddress;
316
- socket.remotePort = remoteAddress.val.port;
317
- return new Promise((resolve, reject) => {
318
- function connectOk() {
319
- if (socket.state === SOCKET_STATE_INIT) {
320
- socket.udpSocket.setTTL(socket.unicastHopLimit);
321
- socket.udpSocket.setRecvBufferSize(socket.sendBufferSize);
322
- socket.udpSocket.setSendBufferSize(
323
- socket.receiveBufferSize
324
- );
325
- }
326
- udpSocket.off('error', connectErr);
327
- socket.state = SOCKET_STATE_CONNECTION;
328
- resolve([
329
- (socket.incomingDatagramStream =
330
- createIncomingDatagramStream(socket)).id,
331
- (socket.outgoingDatagramStream =
332
- createOutgoingDatagramStream(socket)).id,
333
- ]);
334
- }
335
- function connectErr(err) {
336
- udpSocket.off('connect', connectOk);
337
- reject(convertSocketError(err));
338
- }
339
- udpSocket.once('connect', connectOk);
340
- udpSocket.once('error', connectErr);
341
- udpSocket.connect(remoteAddress.val.port, serializedRemoteAddress);
342
- });
343
- } else {
344
- socket.state = SOCKET_STATE_BOUND;
345
- socket.remoteAddress = null;
346
- socket.remotePort = null;
347
- return [
348
- (socket.incomingDatagramStream =
349
- createIncomingDatagramStream(socket)).id,
350
- (socket.outgoingDatagramStream =
351
- createOutgoingDatagramStream(socket)).id,
352
- ];
353
- }
320
+ udpSocket.off("error", connectErr);
321
+ socket.state = SOCKET_STATE_CONNECTION;
322
+ resolve([
323
+ (socket.incomingDatagramStream = createIncomingDatagramStream(socket)).id,
324
+ (socket.outgoingDatagramStream = createOutgoingDatagramStream(socket)).id,
325
+ ]);
326
+ }
327
+ function connectErr(err) {
328
+ udpSocket.off("connect", connectOk);
329
+ reject(convertSocketError(err));
330
+ }
331
+ udpSocket.once("connect", connectOk);
332
+ udpSocket.once("error", connectErr);
333
+ udpSocket.connect(remoteAddress.val.port, serializedRemoteAddress);
334
+ });
335
+ } else {
336
+ socket.state = SOCKET_STATE_BOUND;
337
+ socket.remoteAddress = null;
338
+ socket.remotePort = null;
339
+ return [
340
+ (socket.incomingDatagramStream = createIncomingDatagramStream(socket)).id,
341
+ (socket.outgoingDatagramStream = createOutgoingDatagramStream(socket)).id,
342
+ ];
343
+ }
354
344
  }
355
345
 
356
346
  export function socketUdpSetReceiveBufferSize(id, bufferSize) {
357
- const socket = udpSockets.get(id);
358
- bufferSize = Number(bufferSize);
359
- if (
360
- socket.state !== SOCKET_STATE_INIT &&
361
- socket.state !== SOCKET_STATE_BIND
362
- ) {
363
- try {
364
- socket.udpSocket.setRecvBufferSize(bufferSize);
365
- } catch (err) {
366
- throw convertSocketError(err);
367
- }
347
+ const socket = udpSockets.get(id);
348
+ bufferSize = Number(bufferSize);
349
+ if (socket.state !== SOCKET_STATE_INIT && socket.state !== SOCKET_STATE_BIND) {
350
+ try {
351
+ socket.udpSocket.setRecvBufferSize(bufferSize);
352
+ } catch (err) {
353
+ throw convertSocketError(err);
368
354
  }
369
- socket.receiveBufferSize = bufferSize;
355
+ }
356
+ socket.receiveBufferSize = bufferSize;
370
357
  }
371
358
 
372
359
  export function socketUdpSetSendBufferSize(id, bufferSize) {
373
- const socket = udpSockets.get(id);
374
- bufferSize = Number(bufferSize);
375
- if (
376
- socket.state !== SOCKET_STATE_INIT &&
377
- socket.state !== SOCKET_STATE_BIND
378
- ) {
379
- try {
380
- socket.udpSocket.setSendBufferSize(bufferSize);
381
- } catch (err) {
382
- throw convertSocketError(err);
383
- }
360
+ const socket = udpSockets.get(id);
361
+ bufferSize = Number(bufferSize);
362
+ if (socket.state !== SOCKET_STATE_INIT && socket.state !== SOCKET_STATE_BIND) {
363
+ try {
364
+ socket.udpSocket.setSendBufferSize(bufferSize);
365
+ } catch (err) {
366
+ throw convertSocketError(err);
384
367
  }
385
- socket.sendBufferSize = bufferSize;
368
+ }
369
+ socket.sendBufferSize = bufferSize;
386
370
  }
387
371
 
388
372
  export function socketUdpSetUnicastHopLimit(id, hopLimit) {
389
- const socket = udpSockets.get(id);
390
- if (
391
- socket.state !== SOCKET_STATE_INIT &&
392
- socket.state !== SOCKET_STATE_BIND
393
- ) {
394
- try {
395
- socket.udpSocket.setTTL(hopLimit);
396
- } catch (err) {
397
- throw convertSocketError(err);
398
- }
373
+ const socket = udpSockets.get(id);
374
+ if (socket.state !== SOCKET_STATE_INIT && socket.state !== SOCKET_STATE_BIND) {
375
+ try {
376
+ socket.udpSocket.setTTL(hopLimit);
377
+ } catch (err) {
378
+ throw convertSocketError(err);
399
379
  }
400
- socket.unicastHopLimit = hopLimit;
380
+ }
381
+ socket.unicastHopLimit = hopLimit;
401
382
  }
402
383
 
403
384
  export async function socketUdpGetReceiveBufferSize(id) {
404
- const socket = udpSockets.get(id);
405
- if (socket.receiveBufferSize) {
406
- return BigInt(socket.receiveBufferSize);
407
- }
408
- if (
409
- socket.state !== SOCKET_STATE_INIT &&
410
- socket.state !== SOCKET_STATE_BIND
411
- ) {
412
- try {
413
- return BigInt(
414
- (socket.receiveBufferSize =
415
- socket.udpSocket.getRecvBufferSize())
416
- );
417
- } catch (err) {
418
- throw convertSocketError(err);
419
- }
420
- } else {
421
- return BigInt(
422
- (socket.receiveBufferSize = await getDefaultReceiveBufferSize())
423
- );
385
+ const socket = udpSockets.get(id);
386
+ if (socket.receiveBufferSize) {
387
+ return BigInt(socket.receiveBufferSize);
388
+ }
389
+ if (socket.state !== SOCKET_STATE_INIT && socket.state !== SOCKET_STATE_BIND) {
390
+ try {
391
+ return BigInt((socket.receiveBufferSize = socket.udpSocket.getRecvBufferSize()));
392
+ } catch (err) {
393
+ throw convertSocketError(err);
424
394
  }
395
+ } else {
396
+ return BigInt((socket.receiveBufferSize = await getDefaultReceiveBufferSize()));
397
+ }
425
398
  }
426
399
 
427
400
  export async function socketUdpGetSendBufferSize(id) {
428
- const socket = udpSockets.get(id);
429
- if (socket.sendBufferSize) {
430
- return BigInt(socket.sendBufferSize);
431
- }
432
- if (
433
- socket.state !== SOCKET_STATE_INIT &&
434
- socket.state !== SOCKET_STATE_BIND
435
- ) {
436
- try {
437
- return BigInt(
438
- (socket.sendBufferSize = socket.udpSocket.getSendBufferSize())
439
- );
440
- } catch (err) {
441
- throw convertSocketError(err);
442
- }
443
- } else {
444
- return BigInt(
445
- (socket.sendBufferSize = await getDefaultSendBufferSize())
446
- );
401
+ const socket = udpSockets.get(id);
402
+ if (socket.sendBufferSize) {
403
+ return BigInt(socket.sendBufferSize);
404
+ }
405
+ if (socket.state !== SOCKET_STATE_INIT && socket.state !== SOCKET_STATE_BIND) {
406
+ try {
407
+ return BigInt((socket.sendBufferSize = socket.udpSocket.getSendBufferSize()));
408
+ } catch (err) {
409
+ throw convertSocketError(err);
447
410
  }
411
+ } else {
412
+ return BigInt((socket.sendBufferSize = await getDefaultSendBufferSize()));
413
+ }
448
414
  }
449
415
 
450
416
  export function socketUdpGetUnicastHopLimit(id) {
451
- const { unicastHopLimit } = udpSockets.get(id);
452
- return unicastHopLimit;
417
+ const { unicastHopLimit } = udpSockets.get(id);
418
+ return unicastHopLimit;
453
419
  }
454
420
 
455
421
  export function socketUdpDispose(id) {
456
- const { udpSocket } = udpSockets.get(id);
457
- return new Promise((resolve) => {
458
- udpSocket.close(() => {
459
- udpSockets.delete(id);
460
- resolve(0);
461
- });
422
+ const { udpSocket } = udpSockets.get(id);
423
+ return new Promise((resolve) => {
424
+ udpSocket.close(() => {
425
+ udpSockets.delete(id);
426
+ resolve(0);
462
427
  });
428
+ });
463
429
  }
464
430
 
465
431
  export function socketIncomingDatagramStreamReceive(id, maxResults) {
466
- const datagramStream = datagramStreams.get(id);
467
- if (!datagramStream.active) {
468
- throw new Error(
469
- 'wasi-io trap: attempt to receive on inactive incoming datagram stream'
470
- );
471
- }
472
- if (maxResults === 0n || datagramStream.queue.length === 0) {
473
- return [];
474
- }
475
- if (datagramStream.error) {
476
- throw convertSocketError(datagramStream.error);
477
- }
478
- return datagramStream.queue.splice(0, Number(maxResults));
432
+ const datagramStream = datagramStreams.get(id);
433
+ if (!datagramStream.active) {
434
+ throw new Error("wasi-io trap: attempt to receive on inactive incoming datagram stream");
435
+ }
436
+ if (maxResults === 0n || datagramStream.queue.length === 0) {
437
+ return [];
438
+ }
439
+ if (datagramStream.error) {
440
+ throw convertSocketError(datagramStream.error);
441
+ }
442
+ return datagramStream.queue.splice(0, Number(maxResults));
479
443
  }
480
444
 
481
445
  export async function socketOutgoingDatagramStreamSend(id, datagrams) {
482
- const { active, socket } = datagramStreams.get(id);
483
- if (!active) {
484
- throw new Error(
485
- 'wasi-io trap: writing to inactive outgoing datagram stream'
486
- );
487
- }
488
-
489
- const { udpSocket } = socket;
490
- let sendQueue = [],
491
- sendQueueAddress,
492
- sendQueuePort;
493
- let datagramsSent = 0;
494
- for (const { data, remoteAddress } of datagrams) {
495
- const address = remoteAddress
496
- ? serializeIpAddress(remoteAddress)
497
- : socket.remoteAddress;
498
- const port = remoteAddress?.val.port ?? socket.remotePort;
499
- let sendLastBatch = !UDP_BATCH_SENDS;
500
- if (sendQueue.length > 0) {
501
- if (sendQueueAddress === address && sendQueuePort === port) {
502
- sendQueue.push(data);
503
- } else {
504
- sendLastBatch = true;
505
- }
506
- } else {
507
- sendQueueAddress = address;
508
- sendQueuePort = port;
509
- sendQueue.push(data);
446
+ const { active, socket } = datagramStreams.get(id);
447
+ if (!active) {
448
+ throw new Error("wasi-io trap: writing to inactive outgoing datagram stream");
449
+ }
450
+
451
+ const { udpSocket } = socket;
452
+ let sendQueue = [],
453
+ sendQueueAddress,
454
+ sendQueuePort;
455
+ let datagramsSent = 0;
456
+ for (const { data, remoteAddress } of datagrams) {
457
+ const address = remoteAddress ? serializeIpAddress(remoteAddress) : socket.remoteAddress;
458
+ const port = remoteAddress?.val.port ?? socket.remotePort;
459
+ let sendLastBatch = !UDP_BATCH_SENDS;
460
+ if (sendQueue.length > 0) {
461
+ if (sendQueueAddress === address && sendQueuePort === port) {
462
+ sendQueue.push(data);
463
+ } else {
464
+ sendLastBatch = true;
465
+ }
466
+ } else {
467
+ sendQueueAddress = address;
468
+ sendQueuePort = port;
469
+ sendQueue.push(data);
470
+ }
471
+ if (sendLastBatch) {
472
+ const err = await doSendBatch();
473
+ if (err) {
474
+ return BigInt(datagramsSent);
475
+ }
476
+ if (UDP_BATCH_SENDS) {
477
+ sendQueue = [data];
478
+ sendQueuePort = port;
479
+ sendQueueAddress = address;
480
+ } else {
481
+ sendQueue = [];
482
+ sendQueuePort = port;
483
+ sendQueueAddress = address;
484
+ }
485
+ }
486
+ }
487
+ if (sendQueue.length) {
488
+ const err = await doSendBatch();
489
+ if (err) {
490
+ return BigInt(datagramsSent);
491
+ }
492
+ }
493
+
494
+ if (datagramsSent !== datagrams.length) {
495
+ throw new Error("wasi-io trap: expected to have sent all the datagrams");
496
+ }
497
+ return BigInt(datagramsSent);
498
+
499
+ function doSendBatch() {
500
+ return new Promise((resolve, reject) => {
501
+ if (socket.remoteAddress) {
502
+ if (sendQueueAddress !== socket.remoteAddress || sendQueuePort !== socket.remotePort) {
503
+ return void reject("invalid-argument");
510
504
  }
511
- if (sendLastBatch) {
512
- const err = await doSendBatch();
513
- if (err) {
514
- return BigInt(datagramsSent);
515
- }
516
- if (UDP_BATCH_SENDS) {
517
- sendQueue = [data];
518
- sendQueuePort = port;
519
- sendQueueAddress = address;
520
- } else {
521
- sendQueue = [];
522
- sendQueuePort = port;
523
- sendQueueAddress = address;
524
- }
505
+ udpSocket.send(sendQueue, handler);
506
+ } else {
507
+ if (!sendQueueAddress) {
508
+ return void reject("invalid-argument");
525
509
  }
526
- }
527
- if (sendQueue.length) {
528
- const err = await doSendBatch();
510
+ udpSocket.send(sendQueue, sendQueuePort, sendQueueAddress, handler);
511
+ }
512
+ function handler(err, _sentBytes) {
529
513
  if (err) {
530
- return BigInt(datagramsSent);
514
+ // TODO: update datagramsSent properly on error for multiple sends
515
+ // to enable send batching. Perhaps a Node.js PR could
516
+ // still set the second sendBytes arg?
517
+ if (datagramsSent > 0) {
518
+ resolve(datagramsSent);
519
+ } else {
520
+ reject(convertSocketError(err));
521
+ }
522
+ return;
531
523
  }
532
- }
533
-
534
- if (datagramsSent !== datagrams.length) {
535
- throw new Error(
536
- 'wasi-io trap: expected to have sent all the datagrams'
537
- );
538
- }
539
- return BigInt(datagramsSent);
540
-
541
- function doSendBatch() {
542
- return new Promise((resolve, reject) => {
543
- if (socket.remoteAddress) {
544
- if (
545
- sendQueueAddress !== socket.remoteAddress ||
546
- sendQueuePort !== socket.remotePort
547
- ) {
548
- return void reject('invalid-argument');
549
- }
550
- udpSocket.send(sendQueue, handler);
551
- } else {
552
- if (!sendQueueAddress) {
553
- return void reject('invalid-argument');
554
- }
555
- udpSocket.send(
556
- sendQueue,
557
- sendQueuePort,
558
- sendQueueAddress,
559
- handler
560
- );
561
- }
562
- function handler(err, _sentBytes) {
563
- if (err) {
564
- // TODO: update datagramsSent properly on error for multiple sends
565
- // to enable send batching. Perhaps a Node.js PR could
566
- // still set the second sendBytes arg?
567
- if (datagramsSent > 0) {
568
- resolve(datagramsSent);
569
- } else {
570
- reject(convertSocketError(err));
571
- }
572
- return;
573
- }
574
- datagramsSent += sendQueue.length;
575
- resolve(false);
576
- }
577
- });
578
- }
524
+ datagramsSent += sendQueue.length;
525
+ resolve(false);
526
+ }
527
+ });
528
+ }
579
529
  }
580
530
 
581
531
  function checkSend(socket) {
582
- try {
583
- return Math.floor(
584
- (socket.udpSocket.getSendBufferSize() -
585
- socket.udpSocket.getSendQueueSize()) /
586
- 1500
587
- );
588
- } catch (err) {
589
- throw convertSocketError(err);
590
- }
532
+ try {
533
+ return Math.floor(
534
+ (socket.udpSocket.getSendBufferSize() - socket.udpSocket.getSendQueueSize()) / 1500,
535
+ );
536
+ } catch (err) {
537
+ throw convertSocketError(err);
538
+ }
591
539
  }
592
540
 
593
541
  function pollSend(socket) {
594
- socket.pollState.ready = false;
595
- // The only way we have of dealing with getting a backpressure
596
- // ready signal in Node.js is to just poll on the queue reducing.
597
- // Ideally this should implement backoff on the poll interval,
598
- // but that work should be done alongside careful benchmarking
599
- // in due course.
600
- setTimeout(() => {
601
- const remaining = checkSend(socket);
602
- if (remaining > 0) {
603
- pollStateReady(socket.pollState);
604
- } else {
605
- pollSend(socket);
606
- }
607
- });
542
+ socket.pollState.ready = false;
543
+ // The only way we have of dealing with getting a backpressure
544
+ // ready signal in Node.js is to just poll on the queue reducing.
545
+ // Ideally this should implement backoff on the poll interval,
546
+ // but that work should be done alongside careful benchmarking
547
+ // in due course.
548
+ setTimeout(() => {
549
+ const remaining = checkSend(socket);
550
+ if (remaining > 0) {
551
+ pollStateReady(socket.pollState);
552
+ } else {
553
+ pollSend(socket);
554
+ }
555
+ });
608
556
  }
609
557
 
610
558
  export function socketOutgoingDatagramStreamCheckSend(id) {
611
- const { active, socket } = datagramStreams.get(id);
612
- if (!active) {
613
- throw new Error(
614
- 'wasi-io trap: check send on inactive outgoing datagram stream'
615
- );
616
- }
617
- const remaining = checkSend(socket);
618
- if (remaining <= 0) {
619
- pollSend(socket);
620
- }
621
- return BigInt(remaining);
559
+ const { active, socket } = datagramStreams.get(id);
560
+ if (!active) {
561
+ throw new Error("wasi-io trap: check send on inactive outgoing datagram stream");
562
+ }
563
+ const remaining = checkSend(socket);
564
+ if (remaining <= 0) {
565
+ pollSend(socket);
566
+ }
567
+ return BigInt(remaining);
622
568
  }
623
569
 
624
570
  function socketDatagramStreamClear(datagramStream) {
625
- datagramStream.active = false;
626
- if (datagramStream.cleanup) {
627
- datagramStream.cleanup();
628
- datagramStream.cleanup = null;
629
- }
571
+ datagramStream.active = false;
572
+ if (datagramStream.cleanup) {
573
+ datagramStream.cleanup();
574
+ datagramStream.cleanup = null;
575
+ }
630
576
  }
631
577
 
632
578
  export function socketDatagramStreamDispose(id) {
633
- const datagramStream = datagramStreams.get(id);
634
- datagramStream.active = false;
635
- if (datagramStream.cleanup) {
636
- datagramStream.cleanup();
637
- datagramStream.cleanup = null;
638
- }
639
- verifyPollsDroppedForDrop(datagramStream.pollState, 'datagram stream');
640
- datagramStreams.delete(id);
579
+ const datagramStream = datagramStreams.get(id);
580
+ datagramStream.active = false;
581
+ if (datagramStream.cleanup) {
582
+ datagramStream.cleanup();
583
+ datagramStream.cleanup = null;
584
+ }
585
+ verifyPollsDroppedForDrop(datagramStream.pollState, "datagram stream");
586
+ datagramStreams.delete(id);
641
587
  }