Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit be6aee9

Browse filesBrowse files
Sarat Addepalliaddaleax
authored andcommitted
dgram: allow typed arrays in .send()
PR-URL: #22413 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
1 parent 33b22d7 commit be6aee9
Copy full SHA for be6aee9

File tree

Expand file treeCollapse file tree

5 files changed

+115
-35
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

5 files changed

+115
-35
lines changed
Open diff view settings
Collapse file

‎doc/api/dgram.md‎

Copy file name to clipboardExpand all lines: doc/api/dgram.md
+8-4Lines changed: 8 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,9 @@ if the socket is not connected.
395395
<!-- YAML
396396
added: v0.1.99
397397
changes:
398+
- version: REPLACEME
399+
pr-url: https://github.com/nodejs/node/pull/22413
400+
description: The `msg` parameter can now be any `TypedArray` or `DataView`.
398401
- version: v8.0.0
399402
pr-url: https://github.com/nodejs/node/pull/11985
400403
description: The `msg` parameter can be an `Uint8Array` now.
@@ -414,7 +417,7 @@ changes:
414417
description: Added support for sending data on connected sockets.
415418
-->
416419

417-
* `msg` {Buffer|Uint8Array|string|Array} Message to be sent.
420+
* `msg` {Buffer|TypedArray|DataView|string|Array} Message to be sent.
418421
* `offset` {integer} Offset in the buffer where the message starts.
419422
* `length` {integer} Number of bytes in the message.
420423
* `port` {integer} Destination port.
@@ -427,8 +430,8 @@ specified. Connected sockets, on the other hand, will use their associated
427430
remote endpoint, so the `port` and `address` arguments must not be set.
428431

429432
The `msg` argument contains the message to be sent.
430-
Depending on its type, different behavior can apply. If `msg` is a `Buffer`
431-
or `Uint8Array`,
433+
Depending on its type, different behavior can apply. If `msg` is a `Buffer`,
434+
any `TypedArray` or a `DataView`,
432435
the `offset` and `length` specify the offset within the `Buffer` where the
433436
message begins and the number of bytes in the message, respectively.
434437
If `msg` is a `String`, then it is automatically converted to a `Buffer`
@@ -457,7 +460,8 @@ passed as the first argument to the `callback`. If a `callback` is not given,
457460
the error is emitted as an `'error'` event on the `socket` object.
458461

459462
Offset and length are optional but both *must* be set if either are used.
460-
They are supported only when the first argument is a `Buffer` or `Uint8Array`.
463+
They are supported only when the first argument is a `Buffer`, a `TypedArray`,
464+
or a `DataView`.
461465

462466
This method throws [`ERR_SOCKET_BAD_PORT`][] if called on an unbound socket.
463467

Collapse file

‎lib/dgram.js‎

Copy file name to clipboardExpand all lines: lib/dgram.js
+20-9Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const {
5555
} = require('internal/validators');
5656
const { Buffer } = require('buffer');
5757
const { deprecate } = require('internal/util');
58-
const { isUint8Array } = require('internal/util/types');
58+
const { isArrayBufferView } = require('internal/util/types');
5959
const EventEmitter = require('events');
6060
const {
6161
defaultTriggerAsyncIdScope,
@@ -456,15 +456,19 @@ Socket.prototype.sendto = function(buffer,
456456
function sliceBuffer(buffer, offset, length) {
457457
if (typeof buffer === 'string') {
458458
buffer = Buffer.from(buffer);
459-
} else if (!isUint8Array(buffer)) {
459+
} else if (!isArrayBufferView(buffer)) {
460460
throw new ERR_INVALID_ARG_TYPE('buffer',
461-
['Buffer', 'Uint8Array', 'string'], buffer);
461+
['Buffer',
462+
'TypedArray',
463+
'DataView',
464+
'string'],
465+
buffer);
462466
}
463467

464468
offset = offset >>> 0;
465469
length = length >>> 0;
466470

467-
return buffer.slice(offset, offset + length);
471+
return Buffer.from(buffer.buffer, buffer.byteOffset + offset, length);
468472
}
469473

470474

@@ -475,10 +479,10 @@ function fixBufferList(list) {
475479
const buf = list[i];
476480
if (typeof buf === 'string')
477481
newlist[i] = Buffer.from(buf);
478-
else if (!isUint8Array(buf))
482+
else if (!isArrayBufferView(buf))
479483
return null;
480484
else
481-
newlist[i] = buf;
485+
newlist[i] = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
482486
}
483487

484488
return newlist;
@@ -583,16 +587,23 @@ Socket.prototype.send = function(buffer,
583587
if (!ArrayIsArray(buffer)) {
584588
if (typeof buffer === 'string') {
585589
list = [ Buffer.from(buffer) ];
586-
} else if (!isUint8Array(buffer)) {
590+
} else if (!isArrayBufferView(buffer)) {
587591
throw new ERR_INVALID_ARG_TYPE('buffer',
588-
['Buffer', 'Uint8Array', 'string'],
592+
['Buffer',
593+
'TypedArray',
594+
'DataView',
595+
'string'],
589596
buffer);
590597
} else {
591598
list = [ buffer ];
592599
}
593600
} else if (!(list = fixBufferList(buffer))) {
594601
throw new ERR_INVALID_ARG_TYPE('buffer list arguments',
595-
['Buffer', 'string'], buffer);
602+
['Buffer',
603+
'TypedArray',
604+
'DataView',
605+
'string'],
606+
buffer);
596607
}
597608

598609
if (!connected)
Collapse file

‎test/parallel/test-dgram-send-bad-arguments.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-dgram-send-bad-arguments.js
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function checkArgs(connected) {
3636
code: 'ERR_INVALID_ARG_TYPE',
3737
name: 'TypeError',
3838
message: 'The "buffer" argument must be of type string or an instance ' +
39-
'of Buffer or Uint8Array. Received undefined'
39+
'of Buffer, TypedArray, or DataView. Received undefined'
4040
}
4141
);
4242

@@ -90,7 +90,7 @@ function checkArgs(connected) {
9090
code: 'ERR_INVALID_ARG_TYPE',
9191
name: 'TypeError',
9292
message: 'The "buffer" argument must be of type string or an instance ' +
93-
'of Buffer or Uint8Array. Received type number (23)'
93+
'of Buffer, TypedArray, or DataView. Received type number (23)'
9494
}
9595
);
9696

@@ -101,7 +101,8 @@ function checkArgs(connected) {
101101
code: 'ERR_INVALID_ARG_TYPE',
102102
name: 'TypeError',
103103
message: 'The "buffer list arguments" argument must be of type string ' +
104-
'or an instance of Buffer. Received an instance of Array'
104+
'or an instance of Buffer, TypedArray, or DataView. ' +
105+
'Received an instance of Array'
105106
}
106107
);
107108
}
Collapse file

‎test/parallel/test-dgram-send-default-host.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-dgram-send-default-host.js
+40-12Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ const toSend = [Buffer.alloc(256, 'x'),
1212
'hello'];
1313

1414
const received = [];
15+
let totalBytesSent = 0;
16+
let totalBytesReceived = 0;
17+
const arrayBufferViewsCount = common.getArrayBufferViews(
18+
Buffer.from('')
19+
).length;
1520

1621
client.on('listening', common.mustCall(() => {
1722
const port = client.address().port;
@@ -21,24 +26,47 @@ client.on('listening', common.mustCall(() => {
2126
client.send([toSend[2]], port);
2227
client.send(toSend[3], 0, toSend[3].length, port);
2328

24-
client.send(new Uint8Array(toSend[0]), 0, toSend[0].length, port);
25-
client.send(new Uint8Array(toSend[1]), port);
26-
client.send([new Uint8Array(toSend[2])], port);
27-
client.send(new Uint8Array(Buffer.from(toSend[3])),
28-
0, toSend[3].length, port);
29+
totalBytesSent += toSend.map((buf) => buf.length)
30+
.reduce((a, b) => a + b, 0);
31+
32+
for (const msgBuf of common.getArrayBufferViews(toSend[0])) {
33+
client.send(msgBuf, 0, msgBuf.byteLength, port);
34+
totalBytesSent += msgBuf.byteLength;
35+
}
36+
for (const msgBuf of common.getArrayBufferViews(toSend[1])) {
37+
client.send(msgBuf, port);
38+
totalBytesSent += msgBuf.byteLength;
39+
}
40+
for (const msgBuf of common.getArrayBufferViews(toSend[2])) {
41+
client.send([msgBuf], port);
42+
totalBytesSent += msgBuf.byteLength;
43+
}
2944
}));
3045

3146
client.on('message', common.mustCall((buf, info) => {
3247
received.push(buf.toString());
48+
totalBytesReceived += info.size;
3349

34-
if (received.length === toSend.length * 2) {
35-
// The replies may arrive out of order -> sort them before checking.
36-
received.sort();
37-
38-
const expected = toSend.concat(toSend).map(String).sort();
39-
assert.deepStrictEqual(received, expected);
50+
if (totalBytesReceived === totalBytesSent) {
4051
client.close();
4152
}
42-
}, toSend.length * 2));
53+
// For every buffer in `toSend`, we send the raw Buffer,
54+
// as well as every TypedArray in getArrayBufferViews()
55+
}, toSend.length + (toSend.length - 1) * arrayBufferViewsCount));
56+
57+
client.on('close', common.mustCall((buf, info) => {
58+
// The replies may arrive out of order -> sort them before checking.
59+
received.sort();
60+
61+
const repeated = [...toSend];
62+
for (let i = 0; i < arrayBufferViewsCount; i++) {
63+
repeated.push(...toSend.slice(0, 3));
64+
}
65+
66+
assert.strictEqual(totalBytesSent, totalBytesReceived);
67+
68+
const expected = repeated.map(String).sort();
69+
assert.deepStrictEqual(received, expected);
70+
}));
4371

4472
client.bind(0);
Collapse file

‎test/parallel/test-dgram-udp6-send-default-host.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-dgram-udp6-send-default-host.js
+43-7Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,62 @@ const toSend = [Buffer.alloc(256, 'x'),
1515
'hello'];
1616

1717
const received = [];
18+
let totalBytesSent = 0;
19+
let totalBytesReceived = 0;
20+
const arrayBufferViewLength = common.getArrayBufferViews(
21+
Buffer.from('')
22+
).length;
1823

1924
client.on('listening', common.mustCall(() => {
2025
const port = client.address().port;
26+
2127
client.send(toSend[0], 0, toSend[0].length, port);
2228
client.send(toSend[1], port);
2329
client.send([toSend[2]], port);
2430
client.send(toSend[3], 0, toSend[3].length, port);
31+
32+
totalBytesSent += toSend.map((buf) => buf.length)
33+
.reduce((a, b) => a + b, 0);
34+
35+
for (const msgBuf of common.getArrayBufferViews(toSend[0])) {
36+
client.send(msgBuf, 0, msgBuf.byteLength, port);
37+
totalBytesSent += msgBuf.byteLength;
38+
}
39+
for (const msgBuf of common.getArrayBufferViews(toSend[1])) {
40+
client.send(msgBuf, port);
41+
totalBytesSent += msgBuf.byteLength;
42+
}
43+
for (const msgBuf of common.getArrayBufferViews(toSend[2])) {
44+
client.send([msgBuf], port);
45+
totalBytesSent += msgBuf.byteLength;
46+
}
2547
}));
2648

2749
client.on('message', common.mustCall((buf, info) => {
2850
received.push(buf.toString());
51+
totalBytesReceived += info.size;
2952

30-
if (received.length === toSend.length) {
31-
// The replies may arrive out of order -> sort them before checking.
32-
received.sort();
33-
34-
const expected = toSend.map(String).sort();
35-
assert.deepStrictEqual(received, expected);
53+
if (totalBytesReceived === totalBytesSent) {
3654
client.close();
3755
}
38-
}, toSend.length));
56+
// For every buffer in `toSend`, we send the raw Buffer,
57+
// as well as every TypedArray in getArrayBufferViews()
58+
}, toSend.length + (toSend.length - 1) * arrayBufferViewLength));
59+
60+
client.on('close', common.mustCall((buf, info) => {
61+
// The replies may arrive out of order -> sort them before checking.
62+
received.sort();
63+
64+
const repeated = [...toSend];
65+
for (let i = 0; i < arrayBufferViewLength; i++) {
66+
// We get arrayBufferViews only for toSend[0..2].
67+
repeated.push(...toSend.slice(0, 3));
68+
}
69+
70+
assert.strictEqual(totalBytesSent, totalBytesReceived);
71+
72+
const expected = repeated.map(String).sort();
73+
assert.deepStrictEqual(received, expected);
74+
}));
3975

4076
client.bind(0);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.