-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
123 lines (97 loc) · 2.96 KB
/
index.js
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'use strict';
var DiscontinuousRange = require('discontinuous-range');
var headerByteCount = 9;
class DatagramView {
constructor(message, key, datagramMaxSize) {
this.message = message;
this.key = key;
this.datagramMaxSize = datagramMaxSize;
this.payloadMaxSize = datagramMaxSize - headerByteCount;
if (0 === message.length % this.payloadMaxSize) {
this.numberOfDatagrams = Math.floor(message.length / this.payloadMaxSize);
} else {
this.numberOfDatagrams = Math.floor(message.length / this.payloadMaxSize) + 1;
}
}
getDatagram(index) {
var start = index * this.payloadMaxSize;
var end = Math.min(start + this.payloadMaxSize, this.message.length);
var datagram = new Buffer(9 + end - start);
datagram[0] = this.key;
var _offset = start;
var messageLength = this.message.length;
for (var i = 0; i < 4; i++) {
// write offset
datagram[1 + i] = _offset & 255;
_offset = _offset >> 8;
// write message length
datagram[5 + i] = messageLength & 255;
messageLength = messageLength >> 8;
}
this.message.copy(datagram, 9, start, end);
return datagram;
}
}
class MessageBuilder {
constructor(messageLength, messageManager, onComplete) {
this.remainingIndices = new DiscontinuousRange(0, messageLength);
this.buffer = new Buffer(messageLength);
this.messageManager = messageManager;
this.onComplete = onComplete;
}
insert(datagram, bufferOffset) {
var addedLength = datagram.length - 9;
var insertedRange = new DiscontinuousRange(bufferOffset, bufferOffset + addedLength);
this.remainingIndices.subtract(insertedRange);
datagram.copy(this.buffer, bufferOffset, 9, datagram.length);
if (0 === this.remainingIndices.ranges.length) {
this.onComplete(this.messageManager, this.buffer);
}
}
}
class MessageManager {
constructor(onMessage) {
this.builders = {};
this.onMessage = onMessage;
}
getDatagramHeader(datagram) {
if (datagram.length <= headerByteCount) { return null; }
var offset = 0;
var messageLength = 0;
for (var i = 4; 0 <= i; --i) {
// read offset
offset <<= 8;
offset += datagram[1 + i];
// read message length
messageLength <<= 8;
messageLength += datagram[5 + i];
}
return {
key: datagram[0],
offset: offset,
messageLength: messageLength
}
}
processDatagram(datagram) {
var header = this.getDatagramHeader(datagram);
if (null === header) {
throw 'invalid datagram'
}
var key = header.key;
if (!(key in this.builders)) {
var onComplete = function(messageManager, buffer) {
console.log('Received last message with key ' + header.key);
messageManager.onMessage(buffer);
delete messageManager.builders[key];
}
console.log('Received first message with key ' + header.key);
this.builders[key] = new MessageBuilder(header.messageLength, this, onComplete);
}
var builder = this.builders[key];
builder.insert(datagram, header.offset);
}
}
module.exports = {
DatagramView: DatagramView,
MessageManager: MessageManager
};