Kea 2.5.8
txt_like.h
Go to the documentation of this file.
1// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#ifndef TXT_LIKE_H
8#define TXT_LIKE_H
9
10#include <dns/master_lexer.h>
11#include <dns/char_string.h>
12
13#include <stdint.h>
14#include <algorithm>
15#include <string>
16#include <sstream>
17#include <vector>
18
19namespace isc {
20namespace dns {
21namespace rdata {
22namespace generic {
23namespace detail {
24
31template<class Type, uint16_t typeCode>class TXTLikeImpl {
32public:
43 TXTLikeImpl(util::InputBuffer& buffer, size_t rdata_len) {
44 if (rdata_len > MAX_RDLENGTH) {
45 isc_throw(InvalidRdataLength, "RDLENGTH too large: " << rdata_len);
46 }
47
48 if (rdata_len == 0) { // note that this couldn't happen in the loop.
49 isc_throw(DNSMessageFORMERR, "Error in parsing " <<
50 RRType(typeCode) << " RDATA: 0-length character string");
51 }
52
53 do {
54 const uint8_t len = buffer.readUint8();
55 if (rdata_len < len + 1) {
56 isc_throw(DNSMessageFORMERR, "Error in parsing " <<
57 RRType(typeCode) <<
58 " RDATA: character string length is too large: " <<
59 static_cast<int>(len));
60 }
61 std::vector<uint8_t> data(len + 1);
62 data[0] = len;
63 buffer.readData(&data[0] + 1, len);
64 string_list_.push_back(data);
65
66 rdata_len -= (len + 1);
67 } while (rdata_len > 0);
68 }
69
74 explicit TXTLikeImpl(const std::string& txtstr) {
75 std::istringstream ss(txtstr);
76 MasterLexer lexer;
77 lexer.pushSource(ss);
78
79 try {
80 buildFromTextHelper(lexer);
82 isc_throw(InvalidRdataText, "Failed to construct " <<
83 RRType(typeCode) << " RDATA from '" << txtstr <<
84 "': extra new line");
85 }
86 } catch (const MasterLexer::LexerError& ex) {
87 isc_throw(InvalidRdataText, "Failed to construct " <<
88 RRType(typeCode) << " RDATA from '" << txtstr << "': "
89 << ex.what());
90 }
91 }
92
101 buildFromTextHelper(lexer);
102 }
103
104private:
105 void buildFromTextHelper(MasterLexer& lexer) {
106 while (true) {
107 const MasterToken& token = lexer.getNextToken(
109 if (token.getType() != MasterToken::STRING &&
110 token.getType() != MasterToken::QSTRING) {
111 break;
112 }
113 string_list_.push_back(std::vector<uint8_t>());
114 stringToCharString(token.getStringRegion(), string_list_.back());
115 }
116
117 // Let upper layer handle eol/eof.
118 lexer.ungetToken();
119
120 if (string_list_.empty()) {
121 isc_throw(InvalidRdataText, "Failed to construct " <<
122 RRType(typeCode) << " RDATA: empty input");
123 }
124 }
125
126public:
130 TXTLikeImpl(const TXTLikeImpl& other) :
131 string_list_(other.string_list_)
132 {}
133
138 void
139 toWire(util::OutputBuffer& buffer) const {
140 for (std::vector<std::vector<uint8_t> >::const_iterator it =
141 string_list_.begin();
142 it != string_list_.end();
143 ++it)
144 {
145 buffer.writeData(&(*it)[0], (*it).size());
146 }
147 }
148
154 void
156 for (std::vector<std::vector<uint8_t> >::const_iterator it =
157 string_list_.begin();
158 it != string_list_.end();
159 ++it)
160 {
161 renderer.writeData(&(*it)[0], (*it).size());
162 }
163 }
164
168 std::string
169 toText() const {
170 std::string s;
171
172 for (std::vector<std::vector<uint8_t> >::const_iterator it =
173 string_list_.begin(); it != string_list_.end(); ++it)
174 {
175 if (!s.empty()) {
176 s.push_back(' ');
177 }
178 s.push_back('"');
179 s.append(charStringToString(*it));
180 s.push_back('"');
181 }
182
183 return (s);
184 }
185
196 int
197 compare(const TXTLikeImpl& other) const {
198 // This implementation is not efficient. Revisit this (TBD).
199 util::OutputBuffer this_buffer(0);
200 toWire(this_buffer);
201 uint8_t const* const this_data = (uint8_t const*)this_buffer.getData();
202 const size_t this_len = this_buffer.getLength();
203
204 util::OutputBuffer other_buffer(0);
205 other.toWire(other_buffer);
206 uint8_t const* const other_data
207 = (uint8_t const*)other_buffer.getData();
208 const size_t other_len = other_buffer.getLength();
209
210 const size_t cmplen = std::min(this_len, other_len);
211 const int cmp = memcmp(this_data, other_data, cmplen);
212
213 if (cmp != 0) {
214 return (cmp);
215 } else {
216 return ((this_len == other_len) ? 0 :
217 (this_len < other_len) ? -1 : 1);
218 }
219 }
220
221private:
224 std::vector<std::vector<uint8_t> > string_list_;
225};
226
227} // namespace detail
228} // namespace generic
229} // namespace rdata
230} // namespace dns
231} // namespace isc
232
233#endif // TXT_LIKE_H
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The AbstractMessageRenderer class is an abstract base class that provides common interfaces for rende...
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the internal buffer of the renderer object.
Exception thrown from a wrapper version of MasterLexer::getNextToken() for non fatal errors.
Definition: master_lexer.h:322
Tokenizer for parsing DNS master files.
Definition: master_lexer.h:303
void ungetToken()
Return the last token back to the lexer.
bool pushSource(const char *filename, std::string *error=0)
Open a file and make it the current input source of MasterLexer.
const MasterToken & getNextToken(Options options=NONE)
Parse and return another token from the input.
Tokens for MasterLexer.
Definition: master_lexer.h:40
@ STRING
A single string.
Definition: master_lexer.h:57
@ QSTRING
A single string quoted by double-quotes (").
Definition: master_lexer.h:58
@ END_OF_FILE
End of file detected.
Definition: master_lexer.h:50
Type getType() const
Return the token type.
Definition: master_lexer.h:157
const StringRegion & getStringRegion() const
Return the value of a string-variant token.
Definition: master_lexer.h:166
The RRType class encapsulates DNS resource record types.
Definition: rrtype.h:96
A standard DNS module exception that is thrown if RDATA parser encounters an invalid or inconsistent ...
Definition: rdata.h:34
A standard DNS module exception that is thrown if RDATA parser fails to recognize a given textual rep...
Definition: rdata.h:44
rdata::TXTLikeImpl class represents the TXT-like RDATA for TXT and SPF types.
Definition: txt_like.h:31
TXTLikeImpl(const TXTLikeImpl &other)
The copy constructor.
Definition: txt_like.h:130
TXTLikeImpl(util::InputBuffer &buffer, size_t rdata_len)
Constructor from wire-format data.
Definition: txt_like.h:43
int compare(const TXTLikeImpl &other) const
Compare two instances of TXT-like RDATA.
Definition: txt_like.h:197
std::string toText() const
Convert the TXT-like data to a string.
Definition: txt_like.h:169
TXTLikeImpl(const std::string &txtstr)
Constructor from string.
Definition: txt_like.h:74
TXTLikeImpl(MasterLexer &lexer)
Constructor using the master lexer.
Definition: txt_like.h:100
void toWire(util::OutputBuffer &buffer) const
Render the TXT-like data in the wire format to an OutputBuffer object.
Definition: txt_like.h:139
void toWire(AbstractMessageRenderer &renderer) const
Render the TXT-like data in the wire format to an AbstractMessageRenderer object.
Definition: txt_like.h:155
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition: buffer.h:138
void readData(void *data, size_t len)
Read data of the specified length from the buffer and copy it to the caller supplied buffer.
Definition: buffer.h:226
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:343
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:556
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
Definition: buffer.h:395
size_t getLength() const
Return the length of data written in the buffer.
Definition: buffer.h:409
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::string charStringToString(const CharString &char_string)
Convert a CharString into a textual DNS character-string.
Definition: char_string.cc:121
void stringToCharString(const MasterToken::StringRegion &str_region, CharString &result)
Convert a DNS character-string into corresponding binary data.
Definition: char_string.cc:55
const size_t MAX_RDLENGTH
Possible maximum length of RDATA, which is the maximum unsigned 16 bit value.
Definition: rdata.h:73
Defines the logger used by the top-level component of kea-lfc.