name.js
function _decompressName(buf, offset) {
  var name = '';
  var bytes = 0;

  var octet = buf.readUInt8(offset + bytes);
  bytes += 1;

  // The name is made up of a variable number of labels.  Each label begins
  // with a length octet.  The string of labels is ended by a zero length octet.
  while (octet) {
    var label = null;

    // The first 2-bits of the octet are flags indicating if this is a length
    // value or a label pointer to elsewhere in the packet.
    var flags = octet & 0xc0;

    // If both the top 2-bits of the octet are set, then this is an offset pointer.
    if (flags === 0xc0) {
      // NOTE:  The number of bytes parsed was already incremented.  We need
      //        to re-read that first byte to incorporate it into our pointer
      //        value.  Therefore subtract one from the offset and only add
      //        one additional byte to the parsed count.
      var pointer = buf.readUInt16BE(offset + bytes - 1) & 0x3fff;
      bytes += 1;

      // NOTE:  This will only work if the start of the buffer corresponds to
      //        the start of the packet.  If the packet is embedded in a larger
      //        buffer then we need to pass through the offset to the start of
      //        the packet.
      var res = _decompressName(buf, pointer);
      if (res.error) {
        return res;
      }

      label = res.name;

      if (!label) {
        return {bytesRead: bytes, name: name}
      }

      // Once a pointer is used the name section is complete.  We do not need
      // to keep looking for a zero length octet.  Note there is some logic at
      // the end of the loop we still want to execute, so simply set octet to
      // zero to terminate the loop instead of breaking.
      octet = 0;

    // If neither of the bits are set then the name is stored inline in the
    // following bytes.  The name length is defined by the lower 6-bits of the
    // octet.
    } else if (flags === 0) {
      var length = octet & 0x3f;

      if (offset + bytes + length > buf.length) {
        return {
          error: new Error('Name label too large to fit in remaining packet ' +
                           'bytes.')
        };
      }

      label = buf.toString('ascii', offset + bytes, offset + bytes + length);
      bytes += length;

      // Look for the next label's length octet
      octet = buf.readUInt8(offset + bytes);
      bytes += 1;

    // Any other values are undefined, so throw an error.
    } else {
      return {
        error: new Error('Label length octet at offset [' +
                         (offset + bytes - 1) + '] has unexpected top 2-bits ' +
                         'of [' + flags + '];  should be [' + 0xc0 + '] or ' +
                         '[0].')
      };
    }

    // Append to the last parsed label to the name.  Separate labels with
    // periods.
    if (name.length > 0) {
      name += '.';
    }
    name += label;
  }

  return {bytesRead: bytes, name: name};
}
function _decompressName(buf, offset) {
  var name = '';
  var bytes = 0;

  var octet = buf.readUInt8(offset + bytes);
  bytes += 1;

  // The name is made up of a variable number of labels.  Each label begins
  // with a length octet.  The string of labels is ended by a zero length octet.
  while (octet) {
    var label = null;

    // The first 2-bits of the octet are flags indicating if this is a length
    // value or a label pointer to elsewhere in the packet.
    var flags = octet & 0xc0;

    // If both the top 2-bits of the octet are set, then this is an offset pointer.
    if (flags === 0xc0) {
      // NOTE:  The number of bytes parsed was already incremented.  We need
      //        to re-read that first byte to incorporate it into our pointer
      //        value.  Therefore subtract one from the offset and only add
      //        one additional byte to the parsed count.
      var pointer = buf.readUInt16BE(offset + bytes - 1) & 0x3fff;
      bytes += 1;

      // NOTE:  This will only work if the start of the buffer corresponds to
      //        the start of the packet.  If the packet is embedded in a larger
      //        buffer then we need to pass through the offset to the start of
      //        the packet.
      var res = _decompressName(buf, pointer);
      if (res.error) {
        return res;
      }

      label = res.name;

      if (!label) {
        return {bytesRead: bytes, name: name}
      }

      // Once a pointer is used the name section is complete.  We do not need
      // to keep looking for a zero length octet.  Note there is some logic at
      // the end of the loop we still want to execute, so simply set octet to
      // zero to terminate the loop instead of breaking.
      octet = 0;

    // If neither of the bits are set then the name is stored inline in the
    // following bytes.  The name length is defined by the lower 6-bits of the
    // octet.
    } else if (flags === 0) {
      var length = octet & 0x3f;

      if (offset + bytes + length > buf.length) {
        return {
          error: new Error('Name label too large to fit in remaining packet ' +
                           'bytes.')
        };
      }

      label = buf.toString('ascii', offset + bytes, offset + bytes + length);
      bytes += length;

      // Look for the next label's length octet
      octet = buf.readUInt8(offset + bytes);
      bytes += 1;

    // Any other values are undefined, so throw an error.
    } else {
      return {
        error: new Error('Label length octet at offset [' +
                         (offset + bytes - 1) + '] has unexpected top 2-bits ' +
                         'of [' + flags + '];  should be [' + 0xc0 + '] or ' +
                         '[0].')
      };
    }

    // Append to the last parsed label to the name.  Separate labels with
    // periods.
    if (name.length > 0) {
      name += '.';
    }
    name += label;
  }

  return {bytesRead: bytes, name: name};
}
function _decompressName ( buf , offset ) { var name = '' ; var bytes = 0 ; var octet = buf . readUInt8 ( offset + bytes ) ; bytes += 1 ; // The name is made up of a variable number of labels.  Each label begins // with a length octet.  The string of labels is ended by a zero length octet. while ( octet ) { var label = null ; // The first 2-bits of the octet are flags indicating if this is a length // value or a label pointer to elsewhere in the packet. var flags = octet & 0xc0 ; // If both the top 2-bits of the octet are set, then this is an offset pointer. if ( flags === 0xc0 ) { // NOTE:  The number of bytes parsed was already incremented.  We need //        to re-read that first byte to incorporate it into our pointer //        value.  Therefore subtract one from the offset and only add //        one additional byte to the parsed count. var pointer = buf . readUInt16BE ( offset + bytes - 1 ) & 0x3fff ; bytes += 1 ; // NOTE:  This will only work if the start of the buffer corresponds to //        the start of the packet.  If the packet is embedded in a larger //        buffer then we need to pass through the offset to the start of //        the packet. var res = _decompressName ( buf , pointer ) ; if ( res . error ) { return res ; } label = res . name ; if ( ! label ) { return { bytesRead : bytes , name : name } } // Once a pointer is used the name section is complete.  We do not need // to keep looking for a zero length octet.  Note there is some logic at // the end of the loop we still want to execute, so simply set octet to // zero to terminate the loop instead of breaking. octet = 0 ; // If neither of the bits are set then the name is stored inline in the // following bytes.  The name length is defined by the lower 6-bits of the // octet. } else if ( flags === 0 ) { var length = octet & 0x3f ; if ( offset + bytes + length > buf . length ) { return { error : new Error ( 'Name label too large to fit in remaining packet ' + 'bytes.' ) } ; } label = buf . toString ( 'ascii' , offset + bytes , offset + bytes + length ) ; bytes += length ; // Look for the next label's length octet octet = buf . readUInt8 ( offset + bytes ) ; bytes += 1 ; // Any other values are undefined, so throw an error. } else { return { error : new Error ( 'Label length octet at offset [' + ( offset + bytes - 1 ) + '] has unexpected top 2-bits ' + 'of [' + flags + '];  should be [' + 0xc0 + '] or ' + '[0].' ) } ; } // Append to the last parsed label to the name.  Separate labels with // periods. if ( name . length > 0 ) { name += '.' ; } name += label ; } return { bytesRead : bytes , name : name } ; }
Decompress the name from the packet.  The compression scheme is defined in RFC 883 and is the same method used in DNS packets.  Essentially, names are stored in parts called labels.  Each label is preceded by a 2-bit flag field and 6-bit length field.  In the common case the 2-bits are zero and the length indicates how many bytes are in that label.  The parsing process is terminated by a zero length label.  Alternatively, a the 2-bit flags can both be set indicating a label pointer.  In that case the following 14-bits indicate an offset into the packet from which to read the remaining labels for the name.
Decompress the name from the packet . The compression scheme is defined in RFC 883 and is the same method used in DNS packets . Essentially names are stored in parts called labels . Each label is preceded by a 2 - bit flag field and 6 - bit length field . In the common case the 2 - bits are zero and the length indicates how many bytes are in that label . The parsing process is terminated by a zero length label . Alternatively a the 2 - bit flags can both be set indicating a label pointer . In that case the following 14 - bits indicate an offset into the packet from which to read the remaining labels for the name .