117 lines
4.3 KiB
JavaScript
117 lines
4.3 KiB
JavaScript
(function (exports) {
|
|
'use strict';
|
|
|
|
// Put some documentation here in these comments.
|
|
// See examples of documentation in dns.type.a.js
|
|
// and dns.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_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));
|