|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 |
|
6 /** |
|
7 * This object contains helpers buffering incoming data & deconstructing it |
|
8 * into parcels as well as buffering outgoing data & constructing parcels. |
|
9 * For that it maintains two buffers and corresponding uint8 views, indexes. |
|
10 * |
|
11 * The incoming buffer is a circular buffer where we store incoming data. |
|
12 * As soon as a complete parcel is received, it is processed right away, so |
|
13 * the buffer only needs to be large enough to hold one parcel. |
|
14 * |
|
15 * The outgoing buffer is to prepare outgoing parcels. The index is reset |
|
16 * every time a parcel is sent. |
|
17 */ |
|
18 |
|
19 let Buf = { |
|
20 INT32_MAX: 2147483647, |
|
21 UINT8_SIZE: 1, |
|
22 UINT16_SIZE: 2, |
|
23 UINT32_SIZE: 4, |
|
24 PARCEL_SIZE_SIZE: 4, |
|
25 PDU_HEX_OCTET_SIZE: 4, |
|
26 |
|
27 incomingBufferLength: 1024, |
|
28 incomingBuffer: null, |
|
29 incomingBytes: null, |
|
30 incomingWriteIndex: 0, |
|
31 incomingReadIndex: 0, |
|
32 readIncoming: 0, |
|
33 readAvailable: 0, |
|
34 currentParcelSize: 0, |
|
35 |
|
36 outgoingBufferLength: 1024, |
|
37 outgoingBuffer: null, |
|
38 outgoingBytes: null, |
|
39 outgoingIndex: 0, |
|
40 outgoingBufferCalSizeQueue: null, |
|
41 |
|
42 _init: function() { |
|
43 this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength); |
|
44 this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength); |
|
45 |
|
46 this.incomingBytes = new Uint8Array(this.incomingBuffer); |
|
47 this.outgoingBytes = new Uint8Array(this.outgoingBuffer); |
|
48 |
|
49 // Track where incoming data is read from and written to. |
|
50 this.incomingWriteIndex = 0; |
|
51 this.incomingReadIndex = 0; |
|
52 |
|
53 // Leave room for the parcel size for outgoing parcels. |
|
54 this.outgoingIndex = this.PARCEL_SIZE_SIZE; |
|
55 |
|
56 // How many bytes we've read for this parcel so far. |
|
57 this.readIncoming = 0; |
|
58 |
|
59 // How many bytes available as parcel data. |
|
60 this.readAvailable = 0; |
|
61 |
|
62 // Size of the incoming parcel. If this is zero, we're expecting a new |
|
63 // parcel. |
|
64 this.currentParcelSize = 0; |
|
65 |
|
66 // Queue for storing outgoing override points |
|
67 this.outgoingBufferCalSizeQueue = []; |
|
68 }, |
|
69 |
|
70 /** |
|
71 * Mark current outgoingIndex as start point for calculation length of data |
|
72 * written to outgoingBuffer. |
|
73 * Mark can be nested for here uses queue to remember marks. |
|
74 * |
|
75 * @param writeFunction |
|
76 * Function to write data length into outgoingBuffer, this function is |
|
77 * also used to allocate buffer for data length. |
|
78 * Raw data size(in Uint8) is provided as parameter calling writeFunction. |
|
79 * If raw data size is not in proper unit for writing, user can adjust |
|
80 * the length value in writeFunction before writing. |
|
81 **/ |
|
82 startCalOutgoingSize: function(writeFunction) { |
|
83 let sizeInfo = {index: this.outgoingIndex, |
|
84 write: writeFunction}; |
|
85 |
|
86 // Allocate buffer for data lemgtj. |
|
87 writeFunction.call(0); |
|
88 |
|
89 // Get size of data length buffer for it is not counted into data size. |
|
90 sizeInfo.size = this.outgoingIndex - sizeInfo.index; |
|
91 |
|
92 // Enqueue size calculation information. |
|
93 this.outgoingBufferCalSizeQueue.push(sizeInfo); |
|
94 }, |
|
95 |
|
96 /** |
|
97 * Calculate data length since last mark, and write it into mark position. |
|
98 **/ |
|
99 stopCalOutgoingSize: function() { |
|
100 let sizeInfo = this.outgoingBufferCalSizeQueue.pop(); |
|
101 |
|
102 // Remember current outgoingIndex. |
|
103 let currentOutgoingIndex = this.outgoingIndex; |
|
104 // Calculate data length, in uint8. |
|
105 let writeSize = this.outgoingIndex - sizeInfo.index - sizeInfo.size; |
|
106 |
|
107 // Write data length to mark, use same function for allocating buffer to make |
|
108 // sure there is no buffer overloading. |
|
109 this.outgoingIndex = sizeInfo.index; |
|
110 sizeInfo.write(writeSize); |
|
111 |
|
112 // Restore outgoingIndex. |
|
113 this.outgoingIndex = currentOutgoingIndex; |
|
114 }, |
|
115 |
|
116 /** |
|
117 * Grow the incoming buffer. |
|
118 * |
|
119 * @param min_size |
|
120 * Minimum new size. The actual new size will be the the smallest |
|
121 * power of 2 that's larger than this number. |
|
122 */ |
|
123 growIncomingBuffer: function(min_size) { |
|
124 if (DEBUG) { |
|
125 debug("Current buffer of " + this.incomingBufferLength + |
|
126 " can't handle incoming " + min_size + " bytes."); |
|
127 } |
|
128 let oldBytes = this.incomingBytes; |
|
129 this.incomingBufferLength = |
|
130 2 << Math.floor(Math.log(min_size)/Math.log(2)); |
|
131 if (DEBUG) debug("New incoming buffer size: " + this.incomingBufferLength); |
|
132 this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength); |
|
133 this.incomingBytes = new Uint8Array(this.incomingBuffer); |
|
134 if (this.incomingReadIndex <= this.incomingWriteIndex) { |
|
135 // Read and write index are in natural order, so we can just copy |
|
136 // the old buffer over to the bigger one without having to worry |
|
137 // about the indexes. |
|
138 this.incomingBytes.set(oldBytes, 0); |
|
139 } else { |
|
140 // The write index has wrapped around but the read index hasn't yet. |
|
141 // Write whatever the read index has left to read until it would |
|
142 // circle around to the beginning of the new buffer, and the rest |
|
143 // behind that. |
|
144 let head = oldBytes.subarray(this.incomingReadIndex); |
|
145 let tail = oldBytes.subarray(0, this.incomingReadIndex); |
|
146 this.incomingBytes.set(head, 0); |
|
147 this.incomingBytes.set(tail, head.length); |
|
148 this.incomingReadIndex = 0; |
|
149 this.incomingWriteIndex += head.length; |
|
150 } |
|
151 if (DEBUG) { |
|
152 debug("New incoming buffer size is " + this.incomingBufferLength); |
|
153 } |
|
154 }, |
|
155 |
|
156 /** |
|
157 * Grow the outgoing buffer. |
|
158 * |
|
159 * @param min_size |
|
160 * Minimum new size. The actual new size will be the the smallest |
|
161 * power of 2 that's larger than this number. |
|
162 */ |
|
163 growOutgoingBuffer: function(min_size) { |
|
164 if (DEBUG) { |
|
165 debug("Current buffer of " + this.outgoingBufferLength + |
|
166 " is too small."); |
|
167 } |
|
168 let oldBytes = this.outgoingBytes; |
|
169 this.outgoingBufferLength = |
|
170 2 << Math.floor(Math.log(min_size)/Math.log(2)); |
|
171 this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength); |
|
172 this.outgoingBytes = new Uint8Array(this.outgoingBuffer); |
|
173 this.outgoingBytes.set(oldBytes, 0); |
|
174 if (DEBUG) { |
|
175 debug("New outgoing buffer size is " + this.outgoingBufferLength); |
|
176 } |
|
177 }, |
|
178 |
|
179 /** |
|
180 * Functions for reading data from the incoming buffer. |
|
181 * |
|
182 * These are all little endian, apart from readParcelSize(); |
|
183 */ |
|
184 |
|
185 /** |
|
186 * Ensure position specified is readable. |
|
187 * |
|
188 * @param index |
|
189 * Data position in incoming parcel, valid from 0 to |
|
190 * currentParcelSize. |
|
191 */ |
|
192 ensureIncomingAvailable: function(index) { |
|
193 if (index >= this.currentParcelSize) { |
|
194 throw new Error("Trying to read data beyond the parcel end!"); |
|
195 } else if (index < 0) { |
|
196 throw new Error("Trying to read data before the parcel begin!"); |
|
197 } |
|
198 }, |
|
199 |
|
200 /** |
|
201 * Seek in current incoming parcel. |
|
202 * |
|
203 * @param offset |
|
204 * Seek offset in relative to current position. |
|
205 */ |
|
206 seekIncoming: function(offset) { |
|
207 // Translate to 0..currentParcelSize |
|
208 let cur = this.currentParcelSize - this.readAvailable; |
|
209 |
|
210 let newIndex = cur + offset; |
|
211 this.ensureIncomingAvailable(newIndex); |
|
212 |
|
213 // ... incomingReadIndex -->| |
|
214 // 0 new cur currentParcelSize |
|
215 // |================|=======|====================| |
|
216 // |<-- cur -->|<- readAvailable ->| |
|
217 // |<-- newIndex -->|<-- new readAvailable -->| |
|
218 this.readAvailable = this.currentParcelSize - newIndex; |
|
219 |
|
220 // Translate back: |
|
221 if (this.incomingReadIndex < cur) { |
|
222 // The incomingReadIndex is wrapped. |
|
223 newIndex += this.incomingBufferLength; |
|
224 } |
|
225 newIndex += (this.incomingReadIndex - cur); |
|
226 newIndex %= this.incomingBufferLength; |
|
227 this.incomingReadIndex = newIndex; |
|
228 }, |
|
229 |
|
230 readUint8Unchecked: function() { |
|
231 let value = this.incomingBytes[this.incomingReadIndex]; |
|
232 this.incomingReadIndex = (this.incomingReadIndex + 1) % |
|
233 this.incomingBufferLength; |
|
234 return value; |
|
235 }, |
|
236 |
|
237 readUint8: function() { |
|
238 // Translate to 0..currentParcelSize |
|
239 let cur = this.currentParcelSize - this.readAvailable; |
|
240 this.ensureIncomingAvailable(cur); |
|
241 |
|
242 this.readAvailable--; |
|
243 return this.readUint8Unchecked(); |
|
244 }, |
|
245 |
|
246 readUint8Array: function(length) { |
|
247 // Translate to 0..currentParcelSize |
|
248 let last = this.currentParcelSize - this.readAvailable; |
|
249 last += (length - 1); |
|
250 this.ensureIncomingAvailable(last); |
|
251 |
|
252 let array = new Uint8Array(length); |
|
253 for (let i = 0; i < length; i++) { |
|
254 array[i] = this.readUint8Unchecked(); |
|
255 } |
|
256 |
|
257 this.readAvailable -= length; |
|
258 return array; |
|
259 }, |
|
260 |
|
261 readUint16: function() { |
|
262 return this.readUint8() | this.readUint8() << 8; |
|
263 }, |
|
264 |
|
265 readInt32: function() { |
|
266 return this.readUint8() | this.readUint8() << 8 | |
|
267 this.readUint8() << 16 | this.readUint8() << 24; |
|
268 }, |
|
269 |
|
270 readInt32List: function() { |
|
271 let length = this.readInt32(); |
|
272 let ints = []; |
|
273 for (let i = 0; i < length; i++) { |
|
274 ints.push(this.readInt32()); |
|
275 } |
|
276 return ints; |
|
277 }, |
|
278 |
|
279 readString: function() { |
|
280 let string_len = this.readInt32(); |
|
281 if (string_len < 0 || string_len >= this.INT32_MAX) { |
|
282 return null; |
|
283 } |
|
284 let s = ""; |
|
285 for (let i = 0; i < string_len; i++) { |
|
286 s += String.fromCharCode(this.readUint16()); |
|
287 } |
|
288 // Strings are \0\0 delimited, but that isn't part of the length. And |
|
289 // if the string length is even, the delimiter is two characters wide. |
|
290 // It's insane, I know. |
|
291 this.readStringDelimiter(string_len); |
|
292 return s; |
|
293 }, |
|
294 |
|
295 readStringList: function() { |
|
296 let num_strings = this.readInt32(); |
|
297 let strings = []; |
|
298 for (let i = 0; i < num_strings; i++) { |
|
299 strings.push(this.readString()); |
|
300 } |
|
301 return strings; |
|
302 }, |
|
303 |
|
304 readStringDelimiter: function(length) { |
|
305 let delimiter = this.readUint16(); |
|
306 if (!(length & 1)) { |
|
307 delimiter |= this.readUint16(); |
|
308 } |
|
309 if (DEBUG) { |
|
310 if (delimiter !== 0) { |
|
311 debug("Something's wrong, found string delimiter: " + delimiter); |
|
312 } |
|
313 } |
|
314 }, |
|
315 |
|
316 readParcelSize: function() { |
|
317 return this.readUint8Unchecked() << 24 | |
|
318 this.readUint8Unchecked() << 16 | |
|
319 this.readUint8Unchecked() << 8 | |
|
320 this.readUint8Unchecked(); |
|
321 }, |
|
322 |
|
323 /** |
|
324 * Functions for writing data to the outgoing buffer. |
|
325 */ |
|
326 |
|
327 /** |
|
328 * Ensure position specified is writable. |
|
329 * |
|
330 * @param index |
|
331 * Data position in outgoing parcel, valid from 0 to |
|
332 * outgoingBufferLength. |
|
333 */ |
|
334 ensureOutgoingAvailable: function(index) { |
|
335 if (index >= this.outgoingBufferLength) { |
|
336 this.growOutgoingBuffer(index + 1); |
|
337 } |
|
338 }, |
|
339 |
|
340 writeUint8: function(value) { |
|
341 this.ensureOutgoingAvailable(this.outgoingIndex); |
|
342 |
|
343 this.outgoingBytes[this.outgoingIndex] = value; |
|
344 this.outgoingIndex++; |
|
345 }, |
|
346 |
|
347 writeUint16: function(value) { |
|
348 this.writeUint8(value & 0xff); |
|
349 this.writeUint8((value >> 8) & 0xff); |
|
350 }, |
|
351 |
|
352 writeInt32: function(value) { |
|
353 this.writeUint8(value & 0xff); |
|
354 this.writeUint8((value >> 8) & 0xff); |
|
355 this.writeUint8((value >> 16) & 0xff); |
|
356 this.writeUint8((value >> 24) & 0xff); |
|
357 }, |
|
358 |
|
359 writeString: function(value) { |
|
360 if (value == null) { |
|
361 this.writeInt32(-1); |
|
362 return; |
|
363 } |
|
364 this.writeInt32(value.length); |
|
365 for (let i = 0; i < value.length; i++) { |
|
366 this.writeUint16(value.charCodeAt(i)); |
|
367 } |
|
368 // Strings are \0\0 delimited, but that isn't part of the length. And |
|
369 // if the string length is even, the delimiter is two characters wide. |
|
370 // It's insane, I know. |
|
371 this.writeStringDelimiter(value.length); |
|
372 }, |
|
373 |
|
374 writeStringList: function(strings) { |
|
375 this.writeInt32(strings.length); |
|
376 for (let i = 0; i < strings.length; i++) { |
|
377 this.writeString(strings[i]); |
|
378 } |
|
379 }, |
|
380 |
|
381 writeStringDelimiter: function(length) { |
|
382 this.writeUint16(0); |
|
383 if (!(length & 1)) { |
|
384 this.writeUint16(0); |
|
385 } |
|
386 }, |
|
387 |
|
388 writeParcelSize: function(value) { |
|
389 /** |
|
390 * Parcel size will always be the first thing in the parcel byte |
|
391 * array, but the last thing written. Store the current index off |
|
392 * to a temporary to be reset after we write the size. |
|
393 */ |
|
394 let currentIndex = this.outgoingIndex; |
|
395 this.outgoingIndex = 0; |
|
396 this.writeUint8((value >> 24) & 0xff); |
|
397 this.writeUint8((value >> 16) & 0xff); |
|
398 this.writeUint8((value >> 8) & 0xff); |
|
399 this.writeUint8(value & 0xff); |
|
400 this.outgoingIndex = currentIndex; |
|
401 }, |
|
402 |
|
403 copyIncomingToOutgoing: function(length) { |
|
404 if (!length || (length < 0)) { |
|
405 return; |
|
406 } |
|
407 |
|
408 let translatedReadIndexEnd = |
|
409 this.currentParcelSize - this.readAvailable + length - 1; |
|
410 this.ensureIncomingAvailable(translatedReadIndexEnd); |
|
411 |
|
412 let translatedWriteIndexEnd = this.outgoingIndex + length - 1; |
|
413 this.ensureOutgoingAvailable(translatedWriteIndexEnd); |
|
414 |
|
415 let newIncomingReadIndex = this.incomingReadIndex + length; |
|
416 if (newIncomingReadIndex < this.incomingBufferLength) { |
|
417 // Reading won't cause wrapping, go ahead with builtin copy. |
|
418 this.outgoingBytes |
|
419 .set(this.incomingBytes.subarray(this.incomingReadIndex, |
|
420 newIncomingReadIndex), |
|
421 this.outgoingIndex); |
|
422 } else { |
|
423 // Not so lucky. |
|
424 newIncomingReadIndex %= this.incomingBufferLength; |
|
425 this.outgoingBytes |
|
426 .set(this.incomingBytes.subarray(this.incomingReadIndex, |
|
427 this.incomingBufferLength), |
|
428 this.outgoingIndex); |
|
429 if (newIncomingReadIndex) { |
|
430 let firstPartLength = this.incomingBufferLength - this.incomingReadIndex; |
|
431 this.outgoingBytes.set(this.incomingBytes.subarray(0, newIncomingReadIndex), |
|
432 this.outgoingIndex + firstPartLength); |
|
433 } |
|
434 } |
|
435 |
|
436 this.incomingReadIndex = newIncomingReadIndex; |
|
437 this.readAvailable -= length; |
|
438 this.outgoingIndex += length; |
|
439 }, |
|
440 |
|
441 /** |
|
442 * Parcel management |
|
443 */ |
|
444 |
|
445 /** |
|
446 * Write incoming data to the circular buffer. |
|
447 * |
|
448 * @param incoming |
|
449 * Uint8Array containing the incoming data. |
|
450 */ |
|
451 writeToIncoming: function(incoming) { |
|
452 // We don't have to worry about the head catching the tail since |
|
453 // we process any backlog in parcels immediately, before writing |
|
454 // new data to the buffer. So the only edge case we need to handle |
|
455 // is when the incoming data is larger than the buffer size. |
|
456 let minMustAvailableSize = incoming.length + this.readIncoming; |
|
457 if (minMustAvailableSize > this.incomingBufferLength) { |
|
458 this.growIncomingBuffer(minMustAvailableSize); |
|
459 } |
|
460 |
|
461 // We can let the typed arrays do the copying if the incoming data won't |
|
462 // wrap around the edges of the circular buffer. |
|
463 let remaining = this.incomingBufferLength - this.incomingWriteIndex; |
|
464 if (remaining >= incoming.length) { |
|
465 this.incomingBytes.set(incoming, this.incomingWriteIndex); |
|
466 } else { |
|
467 // The incoming data would wrap around it. |
|
468 let head = incoming.subarray(0, remaining); |
|
469 let tail = incoming.subarray(remaining); |
|
470 this.incomingBytes.set(head, this.incomingWriteIndex); |
|
471 this.incomingBytes.set(tail, 0); |
|
472 } |
|
473 this.incomingWriteIndex = (this.incomingWriteIndex + incoming.length) % |
|
474 this.incomingBufferLength; |
|
475 }, |
|
476 |
|
477 /** |
|
478 * Process incoming data. |
|
479 * |
|
480 * @param incoming |
|
481 * Uint8Array containing the incoming data. |
|
482 */ |
|
483 processIncoming: function(incoming) { |
|
484 if (DEBUG) { |
|
485 debug("Received " + incoming.length + " bytes."); |
|
486 debug("Already read " + this.readIncoming); |
|
487 } |
|
488 |
|
489 this.writeToIncoming(incoming); |
|
490 this.readIncoming += incoming.length; |
|
491 while (true) { |
|
492 if (!this.currentParcelSize) { |
|
493 // We're expecting a new parcel. |
|
494 if (this.readIncoming < this.PARCEL_SIZE_SIZE) { |
|
495 // We don't know how big the next parcel is going to be, need more |
|
496 // data. |
|
497 if (DEBUG) debug("Next parcel size unknown, going to sleep."); |
|
498 return; |
|
499 } |
|
500 this.currentParcelSize = this.readParcelSize(); |
|
501 if (DEBUG) { |
|
502 debug("New incoming parcel of size " + this.currentParcelSize); |
|
503 } |
|
504 // The size itself is not included in the size. |
|
505 this.readIncoming -= this.PARCEL_SIZE_SIZE; |
|
506 } |
|
507 |
|
508 if (this.readIncoming < this.currentParcelSize) { |
|
509 // We haven't read enough yet in order to be able to process a parcel. |
|
510 if (DEBUG) debug("Read " + this.readIncoming + ", but parcel size is " |
|
511 + this.currentParcelSize + ". Going to sleep."); |
|
512 return; |
|
513 } |
|
514 |
|
515 // Alright, we have enough data to process at least one whole parcel. |
|
516 // Let's do that. |
|
517 let expectedAfterIndex = (this.incomingReadIndex + this.currentParcelSize) |
|
518 % this.incomingBufferLength; |
|
519 |
|
520 if (DEBUG) { |
|
521 let parcel; |
|
522 if (expectedAfterIndex < this.incomingReadIndex) { |
|
523 let head = this.incomingBytes.subarray(this.incomingReadIndex); |
|
524 let tail = this.incomingBytes.subarray(0, expectedAfterIndex); |
|
525 parcel = Array.slice(head).concat(Array.slice(tail)); |
|
526 } else { |
|
527 parcel = Array.slice(this.incomingBytes.subarray( |
|
528 this.incomingReadIndex, expectedAfterIndex)); |
|
529 } |
|
530 debug("Parcel (size " + this.currentParcelSize + "): " + parcel); |
|
531 } |
|
532 |
|
533 if (DEBUG) debug("We have at least one complete parcel."); |
|
534 try { |
|
535 this.readAvailable = this.currentParcelSize; |
|
536 this.processParcel(); |
|
537 } catch (ex) { |
|
538 if (DEBUG) debug("Parcel handling threw " + ex + "\n" + ex.stack); |
|
539 } |
|
540 |
|
541 // Ensure that the whole parcel was consumed. |
|
542 if (this.incomingReadIndex != expectedAfterIndex) { |
|
543 if (DEBUG) { |
|
544 debug("Parcel handler didn't consume whole parcel, " + |
|
545 Math.abs(expectedAfterIndex - this.incomingReadIndex) + |
|
546 " bytes left over"); |
|
547 } |
|
548 this.incomingReadIndex = expectedAfterIndex; |
|
549 } |
|
550 this.readIncoming -= this.currentParcelSize; |
|
551 this.readAvailable = 0; |
|
552 this.currentParcelSize = 0; |
|
553 } |
|
554 }, |
|
555 |
|
556 /** |
|
557 * Communicate with the IPC thread. |
|
558 */ |
|
559 sendParcel: function() { |
|
560 // Compute the size of the parcel and write it to the front of the parcel |
|
561 // where we left room for it. Note that he parcel size does not include |
|
562 // the size itself. |
|
563 let parcelSize = this.outgoingIndex - this.PARCEL_SIZE_SIZE; |
|
564 this.writeParcelSize(parcelSize); |
|
565 |
|
566 // This assumes that postRILMessage will make a copy of the ArrayBufferView |
|
567 // right away! |
|
568 let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex); |
|
569 if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel)); |
|
570 this.onSendParcel(parcel); |
|
571 this.outgoingIndex = this.PARCEL_SIZE_SIZE; |
|
572 }, |
|
573 |
|
574 getCurrentParcelSize: function() { |
|
575 return this.currentParcelSize; |
|
576 }, |
|
577 |
|
578 getReadAvailable: function() { |
|
579 return this.readAvailable; |
|
580 } |
|
581 |
|
582 /** |
|
583 * Process one parcel. |
|
584 * |
|
585 * |processParcel| is an implementation provided incoming parcel processing |
|
586 * function invoked when we have received a complete parcel. Implementation |
|
587 * may call multiple read functions to extract data from the incoming buffer. |
|
588 */ |
|
589 //processParcel: function() { |
|
590 // let something = this.readInt32(); |
|
591 // ... |
|
592 //}, |
|
593 |
|
594 /** |
|
595 * Write raw data out to underlying channel. |
|
596 * |
|
597 * |onSendParcel| is an implementation provided stream output function |
|
598 * invoked when we're really going to write something out. We assume the |
|
599 * data are completely copied to some output buffer in this call and may |
|
600 * be destroyed when it's done. |
|
601 * |
|
602 * @param parcel |
|
603 * An array of numeric octet data. |
|
604 */ |
|
605 //onSendParcel: function(parcel) { |
|
606 // ... |
|
607 //} |
|
608 }; |
|
609 |
|
610 module.exports = { Buf: Buf }; |