139 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var debug = require('debug')('mdns-packet:lib:dns:bufferwriter');
 | |
| var util = require('util');
 | |
| var Qap = require('qap');
 | |
| 
 | |
| var BufferConsumer = require('./bufferconsumer');
 | |
| var BufferWriter = module.exports = function (size) {
 | |
|   this.buf = new Buffer(size || 512);
 | |
|   this.buf.fill(0);
 | |
|   this.offset = 0;
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.tell = function () {
 | |
|   return this.offset;
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.buffer = function (v) {
 | |
|   if (typeof v === 'undefined') {
 | |
|     return this;
 | |
|   }
 | |
|   if (v instanceof BufferWriter) {
 | |
|     v = v.dump();
 | |
|   }
 | |
|   if (!(v instanceof Buffer)) {
 | |
|     throw new Error('VariableError: not a buffer');
 | |
|   }
 | |
|   if (v.length > 0) {
 | |
|     v.copy(this.buf, this.offset);
 | |
|     this.offset += v.length;
 | |
|   }
 | |
|   return this;
 | |
| };
 | |
| 
 | |
| //4 bytes
 | |
| BufferWriter.prototype.long = function (v) {
 | |
|   this.buf.writeInt32BE(v, this.offset);
 | |
|   this.offset += 4;
 | |
|   return this;
 | |
| };
 | |
| 
 | |
| //two bytes
 | |
| BufferWriter.prototype.short = function (v) {
 | |
|   this.buf.writeUInt16BE(v & 0xFFFF, this.offset);
 | |
|   this.offset += 2;
 | |
|   return this;
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.seek = function (pos) {
 | |
|   debug('seek(%d)', pos);
 | |
|   if (pos < 0) {
 | |
|     throw new Error('Negative pos not allowed');
 | |
|   }
 | |
|   if (pos > this.buf.length) {
 | |
|     debug('bad packet', this.buffer.toString('hex'));
 | |
|     throw new Error(util.format('Cannot seek after EOF. %d > %d',
 | |
|       pos, this.buf.length));
 | |
|   }
 | |
|   this.offset = pos;
 | |
|   return this;
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.byte = function (v) {
 | |
|   this.buf.writeUInt8(v, this.offset);
 | |
|   this.offset += 1;
 | |
|   return this;
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.slice = function (start, end) {
 | |
|   return this.buf.slice(start, end);
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.indexOf = function (text) {
 | |
|   var qap = new Qap(text);
 | |
|   return qap.parse(this.buf);
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Writes a DNS name. If ref is specified, will finish this name with a
 | |
|  * suffix reference (i.e., 0xc0 <ref>). If not, then will terminate with a NULL
 | |
|  * byte.
 | |
|  */
 | |
| BufferWriter.prototype.name = function (v) {
 | |
|   var self = this;
 | |
|   debug('#name', v);
 | |
|   var ref;
 | |
|   var i;
 | |
|   var j;
 | |
|   var part;
 | |
|   var parts = v.split('.');
 | |
|   var parts2 = v.split('.');
 | |
|   var consumer = new BufferConsumer(self.buf);
 | |
|   var qap = new Qap('');
 | |
|   var lastPart = parts.length;
 | |
|   if (v.length > 0) {
 | |
|     for (i = 0; i < parts.length; i++) {
 | |
|       if (parts[i].length === 0) {
 | |
|         lastPart = i;
 | |
|         continue;
 | |
|       }
 | |
|       part = new Buffer(parts[i]);
 | |
|       qap.set(Buffer.concat([ new Buffer([ part.length ]), part ]));
 | |
|       var location = qap.parse(self.buf)[0];
 | |
|       if (location) {
 | |
|         var tr = consumer.seek(location).name();
 | |
|         if (tr === parts2.join('.')) {
 | |
|           debug('found index: %s, from %s at %d', i, tr, location);
 | |
|           ref = location;
 | |
|           lastPart = i;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       parts2.shift();
 | |
|     }
 | |
|   }
 | |
|   var out = new BufferWriter();
 | |
|   debug('lastPart', lastPart, parts);
 | |
|   for (i = 0; i < lastPart; i++) {
 | |
|     part = new Buffer(parts[i]);
 | |
|     debug('writing part', part);
 | |
|     out.byte(part.length);
 | |
|     for (j = 0; j < part.length; ++j) {
 | |
|       out.byte(part[j]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (ref) {
 | |
|     debug('writing a name ref to %d', ref);
 | |
|     out.byte(0xc0).byte(ref);
 | |
|   }
 | |
|   else {
 | |
|     out.byte(0);
 | |
|   }
 | |
|   this.buffer(out);
 | |
|   return this;
 | |
| };
 | |
| 
 | |
| BufferWriter.prototype.dump = function () {
 | |
|   return this.slice(0, this.tell());
 | |
| };
 |