17#include <boost/array.hpp> 
   18#include <boost/static_assert.hpp> 
   41    OffsetItem(
size_t hash, 
size_t pos, 
size_t len) :
 
   42        hash_(hash), pos_(pos), len_(len) {
 
   65template <
bool CASE_SENSITIVE>
 
   73    NameCompare(
const OutputBuffer& buffer, InputBuffer& name_buf,
 
   75        buffer_(&buffer), name_buf_(&name_buf), hash_(hash) {
 
   78    bool operator()(
const OffsetItem& item)
 const {
 
   81        if (item.hash_  != hash_ || item.len_ != name_buf_->getLength()) {
 
   93        name_buf_->setPosition(0); 
 
   94        uint16_t item_pos = item.pos_;
 
   95        uint16_t item_label_len = 0;
 
   96        for (
size_t i = 0; i < item.len_; ++i, ++item_pos) {
 
   97            item_pos = nextPosition(*buffer_, item_pos, item_label_len);
 
   98            const uint8_t ch1 = (*buffer_)[item_pos];
 
   99            const uint8_t ch2 = name_buf_->readUint8();
 
  100            if (CASE_SENSITIVE) {
 
  115    static uint16_t nextPosition(
const OutputBuffer& buffer,
 
  116                                 uint16_t pos, uint16_t& llen) {
 
  122                pos = (buffer[pos] & ~Name::COMPRESS_POINTER_MARK8) *
 
  123                    256 + buffer[pos + 1];
 
  139    const OutputBuffer* buffer_;
 
  140    InputBuffer* name_buf_;
 
  169        for (
size_t i = 0; i < 
BUCKETS; ++i) {
 
 
  175                        size_t hash, 
bool case_sensitive)
 const {
 
  181        const size_t bucket_id = hash % 
BUCKETS;
 
  183        if (case_sensitive) {
 
  184            found = find_if(
table_[bucket_id].rbegin(),
 
  186                            NameCompare<true>(buffer, name_buf, hash));
 
  188            found = find_if(
table_[bucket_id].rbegin(),
 
  190                            NameCompare<false>(buffer, name_buf, hash));
 
  192        if (found != 
table_[bucket_id].rend()) {
 
  193            return (found->pos_);
 
 
  198    void addOffset(
size_t hash, 
size_t offset, 
size_t len) {
 
  199        table_[hash % 
BUCKETS].push_back(OffsetItem(hash, offset, len));
 
 
 
  230    impl_->msglength_limit_ = 512;
 
  231    impl_->truncated_ = 
false;
 
  240            vector<OffsetItem> new_table;
 
  242            new_table.swap(impl_->table_[i]);
 
  244        impl_->table_[i].clear();
 
 
  250    return (impl_->msglength_limit_);
 
 
  255    impl_->msglength_limit_ = len;
 
 
  260    return (impl_->truncated_);
 
 
  265    impl_->truncated_ = 
true;
 
 
  270    return (impl_->compress_mode_);
 
 
  277                  "compress mode cannot be changed during rendering");
 
  279    impl_->compress_mode_ = mode;
 
 
  291    size_t nlabels_uncomp;
 
  293    const bool case_sensitive = (impl_->compress_mode_ ==
 
  295    for (nlabels_uncomp = 0; nlabels_uncomp < nlabels; ++nlabels_uncomp) {
 
  296        if (nlabels_uncomp > 0) {
 
  306        impl_->seq_hashes_.at(nlabels_uncomp) =
 
  307            sequence.
getHash(impl_->compress_mode_);
 
  309        ptr_offset = impl_->findOffset(
getBuffer(), name_buf,
 
  310                                       impl_->seq_hashes_[nlabels_uncomp],
 
  320    if (nlabels_uncomp > 0 || !compress) {
 
  322        if (compress && nlabels > nlabels_uncomp) {
 
  324            uncomp_sequence.
stripRight(nlabels - nlabels_uncomp);
 
  340    for (
size_t i = 0; i < nlabels_uncomp; ++i) {
 
  341        const uint8_t label_len = 
getBuffer()[offset];
 
  342        if (label_len == 0) { 
 
  350        impl_->addOffset(impl_->seq_hashes_[i], offset, seqlen);
 
  351        offset += (label_len + 1);
 
  352        seqlen -= (label_len + 1);
 
 
  363    local_buffer_(0), buffer_(&local_buffer_) {
 
 
  368    if (buffer && buffer_->
getLength() != 0) {
 
  370                  "MessageRenderer buffer cannot be set when in use");
 
  372    if (!buffer && buffer_ == &local_buffer_) {
 
  374                  "Default MessageRenderer buffer cannot be reset");
 
  380        buffer_ = &local_buffer_;
 
 
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
AbstractMessageRenderer()
The default constructor.
size_t getLength() const
Return the length of data written in the internal buffer.
virtual void clear()
Clear the internal buffer and other internal resources.
const isc::util::OutputBuffer & getBuffer() const
Return the output buffer we render into.
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the internal buffer in network byte order.
CompressMode
Compression mode constants.
void setBuffer(isc::util::OutputBuffer *buffer)
Set or reset a temporary output buffer.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the internal buffer of the renderer object.
Light-weight Accessor to Name data.
size_t getHash(bool case_sensitive) const
Calculate a simple hash for the label sequence.
size_t getLabelCount() const
Returns the current number of labels for this LabelSequence.
void stripLeft(size_t i)
Remove labels from the front of this LabelSequence.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
void stripRight(size_t i)
Remove labels from the end of this LabelSequence.
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
@ CASE_SENSITIVE
Compress names case-sensitive manner.
virtual CompressMode getCompressMode() const
Return the compression mode of the renderer class object.
virtual void setLengthLimit(size_t len)
Set the maximum length of rendered data that can fit in the corresponding DNS message without truncat...
virtual void clear()
Clear the internal buffer and other internal resources.
virtual ~MessageRenderer()
virtual void setTruncated()
Mark the renderer to indicate truncation has occurred while rendering.
virtual bool isTruncated() const
Return whether truncation has occurred while rendering.
virtual void writeName(const Name &name, bool compress=true)
Write a Name object into the internal buffer in wire format, with or without name compression.
virtual size_t getLengthLimit() const
Return the maximum length of rendered data that can fit in the corresponding DNS message without trun...
virtual void setCompressMode(CompressMode mode)
This implementation does not allow this call in the middle of rendering (i.e.
@ CASE_INSENSITIVE
Compress names case-insensitive manner (default)
The Name class encapsulates DNS names.
static const uint16_t MAX_COMPRESS_POINTER
Max possible pointer value for name compression.
static const uint16_t COMPRESS_POINTER_MARK16
A 16-bit masked value indicating a start of compression pointer.
static const size_t MAX_WIRE
Max allowable length of domain names.
static const uint16_t COMPRESS_POINTER_MARK8
A 8-bit masked value indicating a start of compression pointer.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
size_t getLength() const
Return the length of data written in the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
const uint8_t maptolower[]
const uint8_t maptolower[]
Defines the logger used by the top-level component of kea-lfc.
The MessageRendererImpl class is the actual implementation of MessageRenderer.
boost::array< size_t, Name::MAX_LABELS > seq_hashes_
void addOffset(size_t hash, size_t offset, size_t len)
static const size_t RESERVED_ITEMS
static const size_t BUCKETS
uint16_t findOffset(const OutputBuffer &buffer, InputBuffer &name_buf, size_t hash, bool case_sensitive) const
static const uint16_t NO_OFFSET
vector< OffsetItem > table_[BUCKETS]
CompressMode compress_mode_
The name compression mode.
bool truncated_
A boolean flag that indicates truncation has occurred while rendering the data.
MessageRendererImpl()
Constructor.
uint16_t msglength_limit_
The maximum length of rendered data that can fit without truncation.