(function (exports) { 'use strict'; // unpack labels with 0x20 compression pointer support // ui8 is the ArrayBuffer of the entire packet // ptr is the current index of the packet // q = { byteLength: 0, cpcount: 0, labels: [], name: '' } // // NOTE: // "NAME"s are terminated with 0x00 // "RDATA" is terminated by its length exports.DNS_UNPACK_LABELS = function (ui8, ptr, q) { if (q.cpcount > 25) { throw new Error("compression pointer loop detected (over 25 pointers seems like a loop)"); } var total = ptr; var i; var len; var label = []; do { label.length = 0; len = ui8[total]; if (len === undefined){ // RDATA is terminated by undefined, not len === 0 break; } if (0xc0 === len) { var cpptr = ui8[total + 1]; // we're not coming back! ptr = cpptr; if (!q.cpcount) { q.byteLength += 2; // cp and len } q.cpcount += 1; // recursion return exports.DNS_UNPACK_LABELS(ui8, ptr, q); } //str.length = 0; // fast empty array if (ui8.byteLength - total < len) { throw new Error( "Expected a string of length " + len + " but packet itself has " + (ui8.byteLength - total) + " bytes remaining" ); } for (i = 0; i < len; i += 1) { total += 1; // TODO check url-allowable characters label.push(String.fromCharCode(ui8[total])); } if (label.length) { q.labels.push(label.join('')); } total += 1; } while (0 !== len && undefined !== len); //str.pop(); // remove trailing '.' q.name = q.labels.join('.'); if (0 === q.cpcount) { q.byteLength = total - ptr; } return q; }; }('undefined' !== typeof window ? window : exports));