summaryrefslogtreecommitdiffstats
path: root/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/dns/mdns/libmdns/fallback/DataReader.jsm')
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DataReader.jsm133
1 files changed, 133 insertions, 0 deletions
diff --git a/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm b/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm
new file mode 100644
index 000000000..a20c1dc32
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm
@@ -0,0 +1,133 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['DataReader'];
+
+class DataReader {
+ // `data` is `Uint8Array`
+ constructor(data, startByte = 0) {
+ this._data = data;
+ this._cursor = startByte;
+ }
+
+ get buffer() {
+ return this._data.buffer;
+ }
+
+ get data() {
+ return this._data;
+ }
+
+ get eof() {
+ return this._cursor >= this._data.length;
+ }
+
+ getBytes(length = 1) {
+ if (!length) {
+ return new Uint8Array();
+ }
+
+ let end = this._cursor + length;
+ if (end > this._data.length) {
+ return new Uint8Array();
+ }
+
+ let uint8Array = new Uint8Array(this.buffer.slice(this._cursor, end));
+ this._cursor += length;
+
+ return uint8Array;
+ }
+
+ getString(length) {
+ let uint8Array = this.getBytes(length);
+ return _uint8ArrayToString(uint8Array);
+ }
+
+ getValue(length) {
+ let uint8Array = this.getBytes(length);
+ return _uint8ArrayToValue(uint8Array);
+ }
+
+ getLabel(decompressData) {
+ let parts = [];
+ let partLength;
+
+ while ((partLength = this.getValue(1))) {
+ // If a length has been specified instead of a pointer,
+ // read the string of the specified length.
+ if (partLength !== 0xc0) {
+ parts.push(this.getString(partLength));
+ continue;
+ }
+
+ // TODO: Handle case where we have a pointer to the label
+ parts.push(String.fromCharCode(0xc0) + this.getString(1));
+ break;
+ }
+
+ let label = parts.join('.');
+
+ return _decompressLabel(label, decompressData || this._data);
+ }
+}
+
+/**
+ * @private
+ */
+function _uint8ArrayToValue(uint8Array) {
+ let length = uint8Array.length;
+ if (length === 0) {
+ return null;
+ }
+
+ let value = 0;
+ for (let i = 0; i < length; i++) {
+ value = value << 8;
+ value += uint8Array[i];
+ }
+
+ return value;
+}
+
+/**
+ * @private
+ */
+function _uint8ArrayToString(uint8Array) {
+ let length = uint8Array.length;
+ if (length === 0) {
+ return '';
+ }
+
+ let results = [];
+ for (let i = 0; i < length; i += 1024) {
+ results.push(String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024)));
+ }
+
+ return results.join('');
+}
+
+/**
+ * @private
+ */
+function _decompressLabel(label, decompressData) {
+ let result = '';
+
+ for (let i = 0, length = label.length; i < length; i++) {
+ if (label.charCodeAt(i) !== 0xc0) {
+ result += label.charAt(i);
+ continue;
+ }
+
+ i++;
+
+ let reader = new DataReader(decompressData, label.charCodeAt(i));
+ result += _decompressLabel(reader.getLabel(), decompressData);
+ }
+
+ return result;
+}