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 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));
 |