1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/system/gonk/worker_buf.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,610 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 + 1.9 +/** 1.10 + * This object contains helpers buffering incoming data & deconstructing it 1.11 + * into parcels as well as buffering outgoing data & constructing parcels. 1.12 + * For that it maintains two buffers and corresponding uint8 views, indexes. 1.13 + * 1.14 + * The incoming buffer is a circular buffer where we store incoming data. 1.15 + * As soon as a complete parcel is received, it is processed right away, so 1.16 + * the buffer only needs to be large enough to hold one parcel. 1.17 + * 1.18 + * The outgoing buffer is to prepare outgoing parcels. The index is reset 1.19 + * every time a parcel is sent. 1.20 + */ 1.21 + 1.22 +let Buf = { 1.23 + INT32_MAX: 2147483647, 1.24 + UINT8_SIZE: 1, 1.25 + UINT16_SIZE: 2, 1.26 + UINT32_SIZE: 4, 1.27 + PARCEL_SIZE_SIZE: 4, 1.28 + PDU_HEX_OCTET_SIZE: 4, 1.29 + 1.30 + incomingBufferLength: 1024, 1.31 + incomingBuffer: null, 1.32 + incomingBytes: null, 1.33 + incomingWriteIndex: 0, 1.34 + incomingReadIndex: 0, 1.35 + readIncoming: 0, 1.36 + readAvailable: 0, 1.37 + currentParcelSize: 0, 1.38 + 1.39 + outgoingBufferLength: 1024, 1.40 + outgoingBuffer: null, 1.41 + outgoingBytes: null, 1.42 + outgoingIndex: 0, 1.43 + outgoingBufferCalSizeQueue: null, 1.44 + 1.45 + _init: function() { 1.46 + this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength); 1.47 + this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength); 1.48 + 1.49 + this.incomingBytes = new Uint8Array(this.incomingBuffer); 1.50 + this.outgoingBytes = new Uint8Array(this.outgoingBuffer); 1.51 + 1.52 + // Track where incoming data is read from and written to. 1.53 + this.incomingWriteIndex = 0; 1.54 + this.incomingReadIndex = 0; 1.55 + 1.56 + // Leave room for the parcel size for outgoing parcels. 1.57 + this.outgoingIndex = this.PARCEL_SIZE_SIZE; 1.58 + 1.59 + // How many bytes we've read for this parcel so far. 1.60 + this.readIncoming = 0; 1.61 + 1.62 + // How many bytes available as parcel data. 1.63 + this.readAvailable = 0; 1.64 + 1.65 + // Size of the incoming parcel. If this is zero, we're expecting a new 1.66 + // parcel. 1.67 + this.currentParcelSize = 0; 1.68 + 1.69 + // Queue for storing outgoing override points 1.70 + this.outgoingBufferCalSizeQueue = []; 1.71 + }, 1.72 + 1.73 + /** 1.74 + * Mark current outgoingIndex as start point for calculation length of data 1.75 + * written to outgoingBuffer. 1.76 + * Mark can be nested for here uses queue to remember marks. 1.77 + * 1.78 + * @param writeFunction 1.79 + * Function to write data length into outgoingBuffer, this function is 1.80 + * also used to allocate buffer for data length. 1.81 + * Raw data size(in Uint8) is provided as parameter calling writeFunction. 1.82 + * If raw data size is not in proper unit for writing, user can adjust 1.83 + * the length value in writeFunction before writing. 1.84 + **/ 1.85 + startCalOutgoingSize: function(writeFunction) { 1.86 + let sizeInfo = {index: this.outgoingIndex, 1.87 + write: writeFunction}; 1.88 + 1.89 + // Allocate buffer for data lemgtj. 1.90 + writeFunction.call(0); 1.91 + 1.92 + // Get size of data length buffer for it is not counted into data size. 1.93 + sizeInfo.size = this.outgoingIndex - sizeInfo.index; 1.94 + 1.95 + // Enqueue size calculation information. 1.96 + this.outgoingBufferCalSizeQueue.push(sizeInfo); 1.97 + }, 1.98 + 1.99 + /** 1.100 + * Calculate data length since last mark, and write it into mark position. 1.101 + **/ 1.102 + stopCalOutgoingSize: function() { 1.103 + let sizeInfo = this.outgoingBufferCalSizeQueue.pop(); 1.104 + 1.105 + // Remember current outgoingIndex. 1.106 + let currentOutgoingIndex = this.outgoingIndex; 1.107 + // Calculate data length, in uint8. 1.108 + let writeSize = this.outgoingIndex - sizeInfo.index - sizeInfo.size; 1.109 + 1.110 + // Write data length to mark, use same function for allocating buffer to make 1.111 + // sure there is no buffer overloading. 1.112 + this.outgoingIndex = sizeInfo.index; 1.113 + sizeInfo.write(writeSize); 1.114 + 1.115 + // Restore outgoingIndex. 1.116 + this.outgoingIndex = currentOutgoingIndex; 1.117 + }, 1.118 + 1.119 + /** 1.120 + * Grow the incoming buffer. 1.121 + * 1.122 + * @param min_size 1.123 + * Minimum new size. The actual new size will be the the smallest 1.124 + * power of 2 that's larger than this number. 1.125 + */ 1.126 + growIncomingBuffer: function(min_size) { 1.127 + if (DEBUG) { 1.128 + debug("Current buffer of " + this.incomingBufferLength + 1.129 + " can't handle incoming " + min_size + " bytes."); 1.130 + } 1.131 + let oldBytes = this.incomingBytes; 1.132 + this.incomingBufferLength = 1.133 + 2 << Math.floor(Math.log(min_size)/Math.log(2)); 1.134 + if (DEBUG) debug("New incoming buffer size: " + this.incomingBufferLength); 1.135 + this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength); 1.136 + this.incomingBytes = new Uint8Array(this.incomingBuffer); 1.137 + if (this.incomingReadIndex <= this.incomingWriteIndex) { 1.138 + // Read and write index are in natural order, so we can just copy 1.139 + // the old buffer over to the bigger one without having to worry 1.140 + // about the indexes. 1.141 + this.incomingBytes.set(oldBytes, 0); 1.142 + } else { 1.143 + // The write index has wrapped around but the read index hasn't yet. 1.144 + // Write whatever the read index has left to read until it would 1.145 + // circle around to the beginning of the new buffer, and the rest 1.146 + // behind that. 1.147 + let head = oldBytes.subarray(this.incomingReadIndex); 1.148 + let tail = oldBytes.subarray(0, this.incomingReadIndex); 1.149 + this.incomingBytes.set(head, 0); 1.150 + this.incomingBytes.set(tail, head.length); 1.151 + this.incomingReadIndex = 0; 1.152 + this.incomingWriteIndex += head.length; 1.153 + } 1.154 + if (DEBUG) { 1.155 + debug("New incoming buffer size is " + this.incomingBufferLength); 1.156 + } 1.157 + }, 1.158 + 1.159 + /** 1.160 + * Grow the outgoing buffer. 1.161 + * 1.162 + * @param min_size 1.163 + * Minimum new size. The actual new size will be the the smallest 1.164 + * power of 2 that's larger than this number. 1.165 + */ 1.166 + growOutgoingBuffer: function(min_size) { 1.167 + if (DEBUG) { 1.168 + debug("Current buffer of " + this.outgoingBufferLength + 1.169 + " is too small."); 1.170 + } 1.171 + let oldBytes = this.outgoingBytes; 1.172 + this.outgoingBufferLength = 1.173 + 2 << Math.floor(Math.log(min_size)/Math.log(2)); 1.174 + this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength); 1.175 + this.outgoingBytes = new Uint8Array(this.outgoingBuffer); 1.176 + this.outgoingBytes.set(oldBytes, 0); 1.177 + if (DEBUG) { 1.178 + debug("New outgoing buffer size is " + this.outgoingBufferLength); 1.179 + } 1.180 + }, 1.181 + 1.182 + /** 1.183 + * Functions for reading data from the incoming buffer. 1.184 + * 1.185 + * These are all little endian, apart from readParcelSize(); 1.186 + */ 1.187 + 1.188 + /** 1.189 + * Ensure position specified is readable. 1.190 + * 1.191 + * @param index 1.192 + * Data position in incoming parcel, valid from 0 to 1.193 + * currentParcelSize. 1.194 + */ 1.195 + ensureIncomingAvailable: function(index) { 1.196 + if (index >= this.currentParcelSize) { 1.197 + throw new Error("Trying to read data beyond the parcel end!"); 1.198 + } else if (index < 0) { 1.199 + throw new Error("Trying to read data before the parcel begin!"); 1.200 + } 1.201 + }, 1.202 + 1.203 + /** 1.204 + * Seek in current incoming parcel. 1.205 + * 1.206 + * @param offset 1.207 + * Seek offset in relative to current position. 1.208 + */ 1.209 + seekIncoming: function(offset) { 1.210 + // Translate to 0..currentParcelSize 1.211 + let cur = this.currentParcelSize - this.readAvailable; 1.212 + 1.213 + let newIndex = cur + offset; 1.214 + this.ensureIncomingAvailable(newIndex); 1.215 + 1.216 + // ... incomingReadIndex -->| 1.217 + // 0 new cur currentParcelSize 1.218 + // |================|=======|====================| 1.219 + // |<-- cur -->|<- readAvailable ->| 1.220 + // |<-- newIndex -->|<-- new readAvailable -->| 1.221 + this.readAvailable = this.currentParcelSize - newIndex; 1.222 + 1.223 + // Translate back: 1.224 + if (this.incomingReadIndex < cur) { 1.225 + // The incomingReadIndex is wrapped. 1.226 + newIndex += this.incomingBufferLength; 1.227 + } 1.228 + newIndex += (this.incomingReadIndex - cur); 1.229 + newIndex %= this.incomingBufferLength; 1.230 + this.incomingReadIndex = newIndex; 1.231 + }, 1.232 + 1.233 + readUint8Unchecked: function() { 1.234 + let value = this.incomingBytes[this.incomingReadIndex]; 1.235 + this.incomingReadIndex = (this.incomingReadIndex + 1) % 1.236 + this.incomingBufferLength; 1.237 + return value; 1.238 + }, 1.239 + 1.240 + readUint8: function() { 1.241 + // Translate to 0..currentParcelSize 1.242 + let cur = this.currentParcelSize - this.readAvailable; 1.243 + this.ensureIncomingAvailable(cur); 1.244 + 1.245 + this.readAvailable--; 1.246 + return this.readUint8Unchecked(); 1.247 + }, 1.248 + 1.249 + readUint8Array: function(length) { 1.250 + // Translate to 0..currentParcelSize 1.251 + let last = this.currentParcelSize - this.readAvailable; 1.252 + last += (length - 1); 1.253 + this.ensureIncomingAvailable(last); 1.254 + 1.255 + let array = new Uint8Array(length); 1.256 + for (let i = 0; i < length; i++) { 1.257 + array[i] = this.readUint8Unchecked(); 1.258 + } 1.259 + 1.260 + this.readAvailable -= length; 1.261 + return array; 1.262 + }, 1.263 + 1.264 + readUint16: function() { 1.265 + return this.readUint8() | this.readUint8() << 8; 1.266 + }, 1.267 + 1.268 + readInt32: function() { 1.269 + return this.readUint8() | this.readUint8() << 8 | 1.270 + this.readUint8() << 16 | this.readUint8() << 24; 1.271 + }, 1.272 + 1.273 + readInt32List: function() { 1.274 + let length = this.readInt32(); 1.275 + let ints = []; 1.276 + for (let i = 0; i < length; i++) { 1.277 + ints.push(this.readInt32()); 1.278 + } 1.279 + return ints; 1.280 + }, 1.281 + 1.282 + readString: function() { 1.283 + let string_len = this.readInt32(); 1.284 + if (string_len < 0 || string_len >= this.INT32_MAX) { 1.285 + return null; 1.286 + } 1.287 + let s = ""; 1.288 + for (let i = 0; i < string_len; i++) { 1.289 + s += String.fromCharCode(this.readUint16()); 1.290 + } 1.291 + // Strings are \0\0 delimited, but that isn't part of the length. And 1.292 + // if the string length is even, the delimiter is two characters wide. 1.293 + // It's insane, I know. 1.294 + this.readStringDelimiter(string_len); 1.295 + return s; 1.296 + }, 1.297 + 1.298 + readStringList: function() { 1.299 + let num_strings = this.readInt32(); 1.300 + let strings = []; 1.301 + for (let i = 0; i < num_strings; i++) { 1.302 + strings.push(this.readString()); 1.303 + } 1.304 + return strings; 1.305 + }, 1.306 + 1.307 + readStringDelimiter: function(length) { 1.308 + let delimiter = this.readUint16(); 1.309 + if (!(length & 1)) { 1.310 + delimiter |= this.readUint16(); 1.311 + } 1.312 + if (DEBUG) { 1.313 + if (delimiter !== 0) { 1.314 + debug("Something's wrong, found string delimiter: " + delimiter); 1.315 + } 1.316 + } 1.317 + }, 1.318 + 1.319 + readParcelSize: function() { 1.320 + return this.readUint8Unchecked() << 24 | 1.321 + this.readUint8Unchecked() << 16 | 1.322 + this.readUint8Unchecked() << 8 | 1.323 + this.readUint8Unchecked(); 1.324 + }, 1.325 + 1.326 + /** 1.327 + * Functions for writing data to the outgoing buffer. 1.328 + */ 1.329 + 1.330 + /** 1.331 + * Ensure position specified is writable. 1.332 + * 1.333 + * @param index 1.334 + * Data position in outgoing parcel, valid from 0 to 1.335 + * outgoingBufferLength. 1.336 + */ 1.337 + ensureOutgoingAvailable: function(index) { 1.338 + if (index >= this.outgoingBufferLength) { 1.339 + this.growOutgoingBuffer(index + 1); 1.340 + } 1.341 + }, 1.342 + 1.343 + writeUint8: function(value) { 1.344 + this.ensureOutgoingAvailable(this.outgoingIndex); 1.345 + 1.346 + this.outgoingBytes[this.outgoingIndex] = value; 1.347 + this.outgoingIndex++; 1.348 + }, 1.349 + 1.350 + writeUint16: function(value) { 1.351 + this.writeUint8(value & 0xff); 1.352 + this.writeUint8((value >> 8) & 0xff); 1.353 + }, 1.354 + 1.355 + writeInt32: function(value) { 1.356 + this.writeUint8(value & 0xff); 1.357 + this.writeUint8((value >> 8) & 0xff); 1.358 + this.writeUint8((value >> 16) & 0xff); 1.359 + this.writeUint8((value >> 24) & 0xff); 1.360 + }, 1.361 + 1.362 + writeString: function(value) { 1.363 + if (value == null) { 1.364 + this.writeInt32(-1); 1.365 + return; 1.366 + } 1.367 + this.writeInt32(value.length); 1.368 + for (let i = 0; i < value.length; i++) { 1.369 + this.writeUint16(value.charCodeAt(i)); 1.370 + } 1.371 + // Strings are \0\0 delimited, but that isn't part of the length. And 1.372 + // if the string length is even, the delimiter is two characters wide. 1.373 + // It's insane, I know. 1.374 + this.writeStringDelimiter(value.length); 1.375 + }, 1.376 + 1.377 + writeStringList: function(strings) { 1.378 + this.writeInt32(strings.length); 1.379 + for (let i = 0; i < strings.length; i++) { 1.380 + this.writeString(strings[i]); 1.381 + } 1.382 + }, 1.383 + 1.384 + writeStringDelimiter: function(length) { 1.385 + this.writeUint16(0); 1.386 + if (!(length & 1)) { 1.387 + this.writeUint16(0); 1.388 + } 1.389 + }, 1.390 + 1.391 + writeParcelSize: function(value) { 1.392 + /** 1.393 + * Parcel size will always be the first thing in the parcel byte 1.394 + * array, but the last thing written. Store the current index off 1.395 + * to a temporary to be reset after we write the size. 1.396 + */ 1.397 + let currentIndex = this.outgoingIndex; 1.398 + this.outgoingIndex = 0; 1.399 + this.writeUint8((value >> 24) & 0xff); 1.400 + this.writeUint8((value >> 16) & 0xff); 1.401 + this.writeUint8((value >> 8) & 0xff); 1.402 + this.writeUint8(value & 0xff); 1.403 + this.outgoingIndex = currentIndex; 1.404 + }, 1.405 + 1.406 + copyIncomingToOutgoing: function(length) { 1.407 + if (!length || (length < 0)) { 1.408 + return; 1.409 + } 1.410 + 1.411 + let translatedReadIndexEnd = 1.412 + this.currentParcelSize - this.readAvailable + length - 1; 1.413 + this.ensureIncomingAvailable(translatedReadIndexEnd); 1.414 + 1.415 + let translatedWriteIndexEnd = this.outgoingIndex + length - 1; 1.416 + this.ensureOutgoingAvailable(translatedWriteIndexEnd); 1.417 + 1.418 + let newIncomingReadIndex = this.incomingReadIndex + length; 1.419 + if (newIncomingReadIndex < this.incomingBufferLength) { 1.420 + // Reading won't cause wrapping, go ahead with builtin copy. 1.421 + this.outgoingBytes 1.422 + .set(this.incomingBytes.subarray(this.incomingReadIndex, 1.423 + newIncomingReadIndex), 1.424 + this.outgoingIndex); 1.425 + } else { 1.426 + // Not so lucky. 1.427 + newIncomingReadIndex %= this.incomingBufferLength; 1.428 + this.outgoingBytes 1.429 + .set(this.incomingBytes.subarray(this.incomingReadIndex, 1.430 + this.incomingBufferLength), 1.431 + this.outgoingIndex); 1.432 + if (newIncomingReadIndex) { 1.433 + let firstPartLength = this.incomingBufferLength - this.incomingReadIndex; 1.434 + this.outgoingBytes.set(this.incomingBytes.subarray(0, newIncomingReadIndex), 1.435 + this.outgoingIndex + firstPartLength); 1.436 + } 1.437 + } 1.438 + 1.439 + this.incomingReadIndex = newIncomingReadIndex; 1.440 + this.readAvailable -= length; 1.441 + this.outgoingIndex += length; 1.442 + }, 1.443 + 1.444 + /** 1.445 + * Parcel management 1.446 + */ 1.447 + 1.448 + /** 1.449 + * Write incoming data to the circular buffer. 1.450 + * 1.451 + * @param incoming 1.452 + * Uint8Array containing the incoming data. 1.453 + */ 1.454 + writeToIncoming: function(incoming) { 1.455 + // We don't have to worry about the head catching the tail since 1.456 + // we process any backlog in parcels immediately, before writing 1.457 + // new data to the buffer. So the only edge case we need to handle 1.458 + // is when the incoming data is larger than the buffer size. 1.459 + let minMustAvailableSize = incoming.length + this.readIncoming; 1.460 + if (minMustAvailableSize > this.incomingBufferLength) { 1.461 + this.growIncomingBuffer(minMustAvailableSize); 1.462 + } 1.463 + 1.464 + // We can let the typed arrays do the copying if the incoming data won't 1.465 + // wrap around the edges of the circular buffer. 1.466 + let remaining = this.incomingBufferLength - this.incomingWriteIndex; 1.467 + if (remaining >= incoming.length) { 1.468 + this.incomingBytes.set(incoming, this.incomingWriteIndex); 1.469 + } else { 1.470 + // The incoming data would wrap around it. 1.471 + let head = incoming.subarray(0, remaining); 1.472 + let tail = incoming.subarray(remaining); 1.473 + this.incomingBytes.set(head, this.incomingWriteIndex); 1.474 + this.incomingBytes.set(tail, 0); 1.475 + } 1.476 + this.incomingWriteIndex = (this.incomingWriteIndex + incoming.length) % 1.477 + this.incomingBufferLength; 1.478 + }, 1.479 + 1.480 + /** 1.481 + * Process incoming data. 1.482 + * 1.483 + * @param incoming 1.484 + * Uint8Array containing the incoming data. 1.485 + */ 1.486 + processIncoming: function(incoming) { 1.487 + if (DEBUG) { 1.488 + debug("Received " + incoming.length + " bytes."); 1.489 + debug("Already read " + this.readIncoming); 1.490 + } 1.491 + 1.492 + this.writeToIncoming(incoming); 1.493 + this.readIncoming += incoming.length; 1.494 + while (true) { 1.495 + if (!this.currentParcelSize) { 1.496 + // We're expecting a new parcel. 1.497 + if (this.readIncoming < this.PARCEL_SIZE_SIZE) { 1.498 + // We don't know how big the next parcel is going to be, need more 1.499 + // data. 1.500 + if (DEBUG) debug("Next parcel size unknown, going to sleep."); 1.501 + return; 1.502 + } 1.503 + this.currentParcelSize = this.readParcelSize(); 1.504 + if (DEBUG) { 1.505 + debug("New incoming parcel of size " + this.currentParcelSize); 1.506 + } 1.507 + // The size itself is not included in the size. 1.508 + this.readIncoming -= this.PARCEL_SIZE_SIZE; 1.509 + } 1.510 + 1.511 + if (this.readIncoming < this.currentParcelSize) { 1.512 + // We haven't read enough yet in order to be able to process a parcel. 1.513 + if (DEBUG) debug("Read " + this.readIncoming + ", but parcel size is " 1.514 + + this.currentParcelSize + ". Going to sleep."); 1.515 + return; 1.516 + } 1.517 + 1.518 + // Alright, we have enough data to process at least one whole parcel. 1.519 + // Let's do that. 1.520 + let expectedAfterIndex = (this.incomingReadIndex + this.currentParcelSize) 1.521 + % this.incomingBufferLength; 1.522 + 1.523 + if (DEBUG) { 1.524 + let parcel; 1.525 + if (expectedAfterIndex < this.incomingReadIndex) { 1.526 + let head = this.incomingBytes.subarray(this.incomingReadIndex); 1.527 + let tail = this.incomingBytes.subarray(0, expectedAfterIndex); 1.528 + parcel = Array.slice(head).concat(Array.slice(tail)); 1.529 + } else { 1.530 + parcel = Array.slice(this.incomingBytes.subarray( 1.531 + this.incomingReadIndex, expectedAfterIndex)); 1.532 + } 1.533 + debug("Parcel (size " + this.currentParcelSize + "): " + parcel); 1.534 + } 1.535 + 1.536 + if (DEBUG) debug("We have at least one complete parcel."); 1.537 + try { 1.538 + this.readAvailable = this.currentParcelSize; 1.539 + this.processParcel(); 1.540 + } catch (ex) { 1.541 + if (DEBUG) debug("Parcel handling threw " + ex + "\n" + ex.stack); 1.542 + } 1.543 + 1.544 + // Ensure that the whole parcel was consumed. 1.545 + if (this.incomingReadIndex != expectedAfterIndex) { 1.546 + if (DEBUG) { 1.547 + debug("Parcel handler didn't consume whole parcel, " + 1.548 + Math.abs(expectedAfterIndex - this.incomingReadIndex) + 1.549 + " bytes left over"); 1.550 + } 1.551 + this.incomingReadIndex = expectedAfterIndex; 1.552 + } 1.553 + this.readIncoming -= this.currentParcelSize; 1.554 + this.readAvailable = 0; 1.555 + this.currentParcelSize = 0; 1.556 + } 1.557 + }, 1.558 + 1.559 + /** 1.560 + * Communicate with the IPC thread. 1.561 + */ 1.562 + sendParcel: function() { 1.563 + // Compute the size of the parcel and write it to the front of the parcel 1.564 + // where we left room for it. Note that he parcel size does not include 1.565 + // the size itself. 1.566 + let parcelSize = this.outgoingIndex - this.PARCEL_SIZE_SIZE; 1.567 + this.writeParcelSize(parcelSize); 1.568 + 1.569 + // This assumes that postRILMessage will make a copy of the ArrayBufferView 1.570 + // right away! 1.571 + let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex); 1.572 + if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel)); 1.573 + this.onSendParcel(parcel); 1.574 + this.outgoingIndex = this.PARCEL_SIZE_SIZE; 1.575 + }, 1.576 + 1.577 + getCurrentParcelSize: function() { 1.578 + return this.currentParcelSize; 1.579 + }, 1.580 + 1.581 + getReadAvailable: function() { 1.582 + return this.readAvailable; 1.583 + } 1.584 + 1.585 + /** 1.586 + * Process one parcel. 1.587 + * 1.588 + * |processParcel| is an implementation provided incoming parcel processing 1.589 + * function invoked when we have received a complete parcel. Implementation 1.590 + * may call multiple read functions to extract data from the incoming buffer. 1.591 + */ 1.592 + //processParcel: function() { 1.593 + // let something = this.readInt32(); 1.594 + // ... 1.595 + //}, 1.596 + 1.597 + /** 1.598 + * Write raw data out to underlying channel. 1.599 + * 1.600 + * |onSendParcel| is an implementation provided stream output function 1.601 + * invoked when we're really going to write something out. We assume the 1.602 + * data are completely copied to some output buffer in this call and may 1.603 + * be destroyed when it's done. 1.604 + * 1.605 + * @param parcel 1.606 + * An array of numeric octet data. 1.607 + */ 1.608 + //onSendParcel: function(parcel) { 1.609 + // ... 1.610 + //} 1.611 +}; 1.612 + 1.613 +module.exports = { Buf: Buf };