(function (exports) { 'use strict'; // Put some documentation here in these comments. // See examples of documentation in parser/type.a.js // and parser/type.mx.js // If the data type you're wanting to unpack contains labels // (meaning text that will be represented as a period-separated // domain name, i.e. www.google.com) then you will need to use // `unpackLabels`, which has compression pointer support var unpackLabels = exports.DNS_UNPACK_LABELS || require('../dns.unpack-labels.js').DNS_UNPACK_LABELS; // The parser receives exactly 3 parameters as follows: // // ab - an ArrayBuffer containing the whole of the packet as binary // you will use Uint8Array (for which endianness doesn't matter) // and DataView (with wich you MUST always specify 'false' for // Big Endian, which is "network byte order") // // packet - a plain javascript value object (i.e. to/from JSON) that // has all of the currently parsed fields (generally not used), // containing meta data in `header`, and arrays of potentially // parsed (or not yet parsed) records in `question`, `answer`, // `authority`, `additional` // // record - an element of an array in packet (meaning one of `question`, // `answer`, `authority`, `additional`) which has potentially // helpful data about the record such as `rdstart` and `rdlength`, // signifying the type at which the binary segment for this record // begins and its length // exports.DNS_PARSER_TYPE_MX = function (ab, packet, record) { // // Slicing RData // // For various reasons it may be easier to work with a slice of the // ArrayBuffer container the binary packet that just represents the // RData you want to work with starting at 0 and ending at the end of // the Resource Record (aka RData) rather than always adding `rdstart` // to some offset and checking that you don't read past the record's // end (`rdstart + rdlength`) var rdataAb = ab.slice(record.rdstart, record.rdstart + record.rdlength); // // Using Uint8Array // // it's very likely that you'll want to process individual bytes, // for which you would use Uint8Array - for example, if some significant // portion of the record is to be read as a non-label string var ui8 = new Uint8Array(rdataAb); // Example: reading a string whose length is defined by the first byte var len = ui8[0]; var i; record.value = ''; for (i = 0; i < len; i += 1) { record.value += String.fromCharCode(ui8[i]); } // Example: reading a string whose length is terminated with 0 var i; record.value = ''; for (i = 0; i < len; i += 1) { if (0 === ui8[i]) { break; } record.value += String.fromCharCode(ui8[i]); } // // Using DataView // // it's also very likely that you'll want to interpret some variable // byte-width data, such as an id or type number, something of that nature var dv = new DataView(rdataAb); // Example: reading a single-octet type, a sexdectet id, and quad-octet date record.rtype = dv.getUint8(0, false); // start at 0 record.rid = dv.getUint16(1, false); // next is at 1 record.date = new Date(dv.getUint32(3, false) * 1000); // advance 2 more bytes to 3 // the next read, if any, would be at 7 // // Unpacking Labels // // if your data type contains labels (i.e. www.google.com would be represented // as 3 labels and would have the byte sequence 0x03"www"0x06"google"0x03"com), // they may contain compression pointers (represented as 0xc0, meaning 192 in // decimal - outside the ascii range) and they may be terminated either by 0x00 // or by the end of the record, so you should use unpackLabels and provide an // ArrayBuffer that is sliced to the end of your record (otherwise record-length // terminated strings would be misinterpretted overflow) // Example: assuming some label started at the 7th byte var truncatedAb = new Uint8Array(ab.slice(0, record.rdstart + record.rdlength)); var labelData = unpackLabels(truncatedAb, record.rdstart+7, { byteLength: 0, cpcount: 0, labels: [], name: '' }); record.deviceName = labelData.name; // finally, return the record return record; }; }('undefined' !== typeof window ? window : exports));