-
-
Notifications
You must be signed in to change notification settings - Fork 194
Expand file tree
/
Copy pathws-utils.js
More file actions
69 lines (59 loc) · 2.74 KB
/
ws-utils.js
File metadata and controls
69 lines (59 loc) · 2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
*
* @param metadata {Object} Max size can be 4GB
* @param bufferData {ArrayBuffer} [optional]
* @return {ArrayBuffer}
* @private
*/
function mergeMetadataAndArrayBuffer(metadata, bufferData= undefined) {
if (bufferData instanceof ArrayBuffer) {
metadata.hasBufferData = true;
}
bufferData = bufferData || new ArrayBuffer(0);
if (typeof metadata !== 'object') {
throw new Error("metadata should be an object, but was " + typeof metadata);
}
if (!(bufferData instanceof ArrayBuffer)) {
throw new Error("Expected bufferData to be an instance of ArrayBuffer, but was " + typeof bufferData);
}
const metadataString = JSON.stringify(metadata);
const metadataUint8Array = new TextEncoder().encode(metadataString);
const metadataBuffer = metadataUint8Array.buffer;
const sizePrefixLength = 4; // 4 bytes for a 32-bit integer
if (metadataBuffer.byteLength > 4294000000) {
throw new Error("metadata too large. Should be below 4,294MB, but was " + metadataBuffer.byteLength);
}
const concatenatedBuffer = new ArrayBuffer(sizePrefixLength + metadataBuffer.byteLength + bufferData.byteLength);
const concatenatedUint8Array = new Uint8Array(concatenatedBuffer);
// Write the length of metadataBuffer as a 32-bit integer
new DataView(concatenatedBuffer).setUint32(0, metadataBuffer.byteLength, true);
// Copy the metadataUint8Array and bufferData (if provided) to the concatenatedUint8Array
concatenatedUint8Array.set(metadataUint8Array, sizePrefixLength);
if (bufferData.byteLength > 0) {
concatenatedUint8Array.set(new Uint8Array(bufferData), sizePrefixLength + metadataBuffer.byteLength);
}
return concatenatedBuffer;
}
function splitMetadataAndBuffer(concatenatedBuffer) {
if(!(concatenatedBuffer instanceof ArrayBuffer)){
throw new Error("Expected ArrayBuffer message from websocket");
}
const sizePrefixLength = 4;
const buffer1Length = new DataView(concatenatedBuffer).getUint32(0, true); // Little endian
const buffer1 = concatenatedBuffer.slice(sizePrefixLength, sizePrefixLength + buffer1Length);
const metadata = JSON.parse(new TextDecoder().decode(buffer1));
let buffer2;
if (concatenatedBuffer.byteLength > sizePrefixLength + buffer1Length) {
buffer2 = concatenatedBuffer.slice(sizePrefixLength + buffer1Length);
}
if(!buffer2 && metadata.hasBufferData) {
// This happens if the sender is sending 0 length buffer. So we have to create an empty buffer here
buffer2 = new ArrayBuffer(0);
}
return {
metadata,
bufferData: buffer2
};
}
exports.mergeMetadataAndArrayBuffer = mergeMetadataAndArrayBuffer;
exports.splitMetadataAndBuffer = splitMetadataAndBuffer;