85 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| (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;
 | |
|     }
 | |
| 
 | |
|     // Handle message compression pointers. See 4.1.4 of RFC1035 for details.
 | |
|     if (len >= 0xc0) {
 | |
|       var cpptr = ((ui8[total] & 0x3f) << 8) |  ui8[total + 1];
 | |
| 
 | |
|       // We're not coming back, so if this is the first time we're following one of
 | |
|       // these pointers we up the byteLength to mark the pointer as part of the label
 | |
|       if (!q.cpcount) {
 | |
|         q.byteLength += 2; // cp and len
 | |
|       }
 | |
|       q.cpcount += 1;
 | |
| 
 | |
|       // recursion
 | |
|       return exports.DNS_UNPACK_LABELS(ui8, cpptr, q);
 | |
|     }
 | |
| 
 | |
|     //str.length = 0; // fast empty array
 | |
|     if (ui8.byteLength - total < len) {
 | |
|       //console.error('-1', ui8[total - 1]);
 | |
|       //console.error(' 0', ui8[total]);
 | |
|       //console.error(' 1', ui8[total + 1]);
 | |
|       //console.error(' 1', ui8[total + 2]);
 | |
|       throw new Error(
 | |
|         "Expected a string of length " + len
 | |
|           + " but packet itself has " + (ui8.byteLength - total) + " bytes remaining"
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     // Advance the pointer to after the length indicator, then read the string in.
 | |
|     total += 1;
 | |
|     for (i = 0; i < len; i += 1) {
 | |
|       // TODO check url-allowable characters
 | |
|       label.push(String.fromCharCode(ui8[total]));
 | |
|       total += 1;
 | |
|     }
 | |
| 
 | |
|     if (label.length) {
 | |
|       q.labels.push(label.join(''));
 | |
|     }
 | |
| 
 | |
|     // It is important this be done every time, so that if we run into a message compression
 | |
|     // pointer later we still have a record of what was consumed before that.
 | |
|     if (0 === q.cpcount) {
 | |
|       q.byteLength = total - ptr;
 | |
|     }
 | |
|   } while (0 !== len && undefined !== len);
 | |
| 
 | |
|   //str.pop(); // remove trailing '.'
 | |
| 
 | |
|   q.name = q.labels.join('.');
 | |
|   return q;
 | |
| };
 | |
| 
 | |
| }('undefined' !== typeof window ? window : exports));
 |