| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  | (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: '' }
 | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  | //
 | 
					
						
							|  |  |  | // NOTE:
 | 
					
						
							|  |  |  | // "NAME"s are terminated with 0x00
 | 
					
						
							|  |  |  | // "RDATA" is terminated by its length
 | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  | 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]; | 
					
						
							| 
									
										
										
										
											2017-02-02 18:39:32 -07:00
										 |  |  |     if (len === undefined){ | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  |       // RDATA is terminated by undefined, not len === 0
 | 
					
						
							| 
									
										
										
										
											2017-10-09 13:48:54 -06:00
										 |  |  |       q.trunc = true; | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2017-02-02 18:39:32 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |     // Handle message compression pointers. See 4.1.4 of RFC1035 for details.
 | 
					
						
							| 
									
										
										
										
											2017-10-09 13:48:54 -06:00
										 |  |  |     // 0xc0 // 192 // parseInt('11000000', 2).toString(16)
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |     if (len >= 0xc0) { | 
					
						
							| 
									
										
										
										
											2017-10-09 13:48:54 -06:00
										 |  |  |       // Only the two highest bits are used to signify the pointer.
 | 
					
						
							|  |  |  |       // The remaining bits may be used to specify the address of the pointer
 | 
					
						
							|  |  |  |       // (it would seem that only 1 extra bit is actually used since the message size is 512 bytes)
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |       var cpptr = ((ui8[total] & 0x3f) << 8) |  ui8[total + 1]; | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |       // 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
 | 
					
						
							| 
									
										
										
										
											2017-02-11 09:54:27 -07:00
										 |  |  |       if (!q.cpcount) { | 
					
						
							|  |  |  |         q.byteLength += 2; // cp and len
 | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |       q.cpcount += 1; | 
					
						
							| 
									
										
										
										
											2017-02-02 18:39:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  |       // recursion
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |       return exports.DNS_UNPACK_LABELS(ui8, cpptr, q); | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |     //str.length = 0; // fast empty array
 | 
					
						
							|  |  |  |     if (ui8.byteLength - total < len) { | 
					
						
							| 
									
										
										
										
											2017-09-28 13:13:18 -06:00
										 |  |  |       //console.error('-1', ui8[total - 1]);
 | 
					
						
							|  |  |  |       //console.error(' 0', ui8[total]);
 | 
					
						
							|  |  |  |       //console.error(' 1', ui8[total + 1]);
 | 
					
						
							|  |  |  |       //console.error(' 1', ui8[total + 2]);
 | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |       throw new Error( | 
					
						
							|  |  |  |         "Expected a string of length " + len | 
					
						
							|  |  |  |           + " but packet itself has " + (ui8.byteLength - total) + " bytes remaining" | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |     // Advance the pointer to after the length indicator, then read the string in.
 | 
					
						
							|  |  |  |     total += 1; | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |     for (i = 0; i < len; i += 1) { | 
					
						
							|  |  |  |       // TODO check url-allowable characters
 | 
					
						
							|  |  |  |       label.push(String.fromCharCode(ui8[total])); | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |       total += 1; | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  |     if (label.length) { | 
					
						
							|  |  |  |       q.labels.push(label.join('')); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 16:18:48 -06:00
										 |  |  |     // 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; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 19:43:56 -07:00
										 |  |  |   } while (0 !== len && undefined !== len); | 
					
						
							| 
									
										
										
										
											2017-01-28 15:15:27 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   //str.pop(); // remove trailing '.'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   q.name = q.labels.join('.'); | 
					
						
							|  |  |  |   return q; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }('undefined' !== typeof window ? window : exports)); |