31 #include <boost/asio/buffer.hpp> 32 #include <boost/range/adaptor/reversed.hpp> 37 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Block>));
51 :
Block(buffer.getBuffer(), buffer.begin(), buffer.end(), true)
56 :
Block(buffer, buffer->begin(), buffer->end(), true)
62 : m_buffer(std::move(buffer))
65 , m_valueBegin(m_begin)
67 , m_size(m_end - m_begin)
70 BOOST_THROW_EXCEPTION(std::invalid_argument(
"buffer is empty"));
73 const uint8_t* bufferBegin = &
m_buffer->front();
74 const uint8_t* bufferEnd = bufferBegin +
m_buffer->size();
75 if (&*begin < bufferBegin || &*begin > bufferEnd ||
76 &*end < bufferBegin || &*end > bufferEnd) {
77 BOOST_THROW_EXCEPTION(std::invalid_argument(
"begin/end iterators points out of the buffer"));
85 BOOST_THROW_EXCEPTION(Error(
"TLV-LENGTH doesn't match buffer size"));
89 Block::Block(
const Block& block, Buffer::const_iterator begin, Buffer::const_iterator end,
91 : Block(block.m_buffer, begin, end, verifyLength)
96 Buffer::const_iterator begin, Buffer::const_iterator end,
97 Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd)
98 : m_buffer(std::move(buffer))
101 , m_valueBegin(valueBegin)
102 , m_valueEnd(valueEnd)
104 , m_size(m_end - m_begin)
110 const uint8_t* pos = buf;
111 const uint8_t*
const end = buf + bufSize;
117 BOOST_ASSERT(pos <=
end);
118 if (length > static_cast<uint64_t>(
end - pos)) {
119 BOOST_THROW_EXCEPTION(
Error(
"Not enough bytes in the buffer to fully parse TLV"));
122 BOOST_ASSERT(pos > buf);
123 uint64_t typeLengthSize = static_cast<uint64_t>(pos - buf);
124 m_size = typeLengthSize + length;
139 : m_buffer(std::move(value))
140 , m_begin(m_buffer->end())
141 , m_end(m_buffer->end())
142 , m_valueBegin(m_buffer->begin())
143 , m_valueEnd(m_buffer->end())
150 : m_buffer(value.m_buffer)
151 , m_begin(m_buffer->end())
152 , m_end(m_buffer->end())
153 , m_valueBegin(value.begin())
154 , m_valueEnd(value.end())
163 std::istream_iterator<uint8_t>
begin(is >> std::noskipws);
164 std::istream_iterator<uint8_t>
end;
174 BOOST_THROW_EXCEPTION(
Error(
"TLV-LENGTH from stream exceeds limit"));
178 uint8_t* valueBuf = eb.buf();
179 is.read(reinterpret_cast<char*>(valueBuf), length);
180 if (length != static_cast<uint64_t>(is.gcount())) {
181 BOOST_THROW_EXCEPTION(
Error(
"Not enough bytes from stream to fully parse TLV"));
184 eb.prependVarNumber(length);
185 eb.prependVarNumber(
type);
189 return Block(eb.getBuffer());
192 std::tuple<bool, Block>
195 auto begin = buffer->begin() + offset;
201 return std::make_tuple(
false,
Block());
207 return std::make_tuple(
false,
Block());
211 if (length > static_cast<uint64_t>(buffer->end() - pos)) {
212 return std::make_tuple(
false,
Block());
215 return std::make_tuple(
true,
Block(std::move(buffer),
type,
begin, pos + length, pos, pos + length));
218 std::tuple<bool, Block>
221 const uint8_t* pos = buf;
222 const uint8_t*
const end = buf + bufSize;
227 return std::make_tuple(
false,
Block());
232 return std::make_tuple(
false,
Block());
236 if (length > static_cast<uint64_t>(
end - pos)) {
237 return std::make_tuple(
false,
Block());
240 size_t typeLengthSize = pos - buf;
241 auto b = make_shared<Buffer>(buf, pos + length);
242 return std::make_tuple(
true,
Block(b,
type, b->begin(), b->end(),
243 b->begin() + typeLengthSize, b->end()));
259 m_type = std::numeric_limits<uint32_t>::max();
270 Buffer::const_iterator
274 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
279 Buffer::const_iterator
283 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
292 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
301 BOOST_THROW_EXCEPTION(
Error(
"Block size cannot be determined (undefined block size)"));
325 BOOST_THROW_EXCEPTION(
Error(
"Block has no TLV-VALUE"));
342 Buffer::const_iterator pos =
begin;
346 if (length > static_cast<uint64_t>(
end - pos)) {
349 " exceeds TLV-VALUE boundary of parent block"));
353 Buffer::const_iterator subEnd = pos + length;
367 size_t estimatedSize =
encode(estimator);
380 size_t len = encodeValue(estimator);
381 len += estimator.prependVarNumber(len);
382 len += estimator.prependVarNumber(
m_type);
391 len += element.encode(estimator);
400 m_end = encoder.begin();
406 len += element.encode(encoder);
412 len += encoder.prependVarNumber(len);
413 len += encoder.prependVarNumber(
m_type);
424 auto it = this->
find(type);
437 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
446 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
480 Block::operator boost::asio::const_buffer()
const 482 return boost::asio::const_buffer(wire(), size());
497 auto oldFmt = os.flags(std::ios_base::dec);
504 size_t tlvLength = block.encodeValue(estimator);
505 os << block.
type() <<
'[' << tlvLength <<
"]={";
514 os << block.
type() <<
"[empty]";
522 operator "" _block(
const char* input, std::size_t len)
524 namespace t = security::transform;
529 for (
const char* end = input + len; input != end; ++input) {
530 if (std::strchr(
"0123456789ABCDEF", *input) !=
nullptr) {
531 ss.write(reinterpret_cast<const uint8_t*>(input), 1);
538 catch (
const t::Error&) {
539 BOOST_THROW_EXCEPTION(std::invalid_argument(
"input has odd number of hexadecimal digits"));
size_t m_size
total size including Type-Length-Value
shared_ptr< const Buffer > m_buffer
underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields
bool hasWire() const
Check if the Block has fully encoded wire.
static Block fromStream(std::istream &is)
Parse Block from an input stream.
Copyright (c) 2011-2015 Regents of the University of California.
static std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset)
Try to parse Block from a wire buffer.
Buffer::const_iterator m_valueBegin
Buffer::const_iterator m_begin
size_t value_size() const
Get size of TLV-VALUE aka TLV-LENGTH.
std::ostream & operator<<(std::ostream &os, const Data &data)
element_container::const_iterator element_const_iterator
const uint8_t * wire() const
Get pointer to encoded wire.
void parse() const
Parse TLV-VALUE into sub elements.
element_container m_elements
sub elements
Represents a TLV element of NDN packet format.
element_const_iterator elements_begin() const
Equivalent to elements().begin()
element_iterator insert(element_const_iterator pos, const Block &element)
Insert a sub element.
const uint8_t * value() const
Get pointer to TLV-VALUE.
element_iterator erase(element_const_iterator position)
Erase a sub element.
void resetWire()
Reset wire buffer but keep TLV-TYPE and sub elements (if any)
Buffer::const_iterator value_begin() const
Get begin iterator of TLV-VALUE.
Buffer::const_iterator m_valueEnd
bool empty() const
Check if the Block is empty.
size_t size() const
Get size of encoded wire, including Type-Length-Value.
element_const_iterator elements_end() const
Equivalent to elements().end()
const Block & get(uint32_t type) const
Get the first sub element of specified TLV-TYPE.
constexpr size_t sizeOfVarNumber(uint64_t number) noexcept
Get the number of bytes necessary to hold the value of number encoded as VAR-NUMBER.
element_const_iterator find(uint32_t type) const
Find the first sub element of specified TLV-TYPE.
bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
Block & operator=(const Block &)
Copy assignment operator.
Buffer::const_iterator value_end() const
Get end iterator of TLV-VALUE.
ostream_joiner< std::decay_t< DelimT >, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
Buffer::const_iterator begin() const
Get begin iterator of encoded wire.
element_container::iterator element_iterator
void remove(uint32_t type)
Remove all sub elements of specified TLV-TYPE.
void reset()
Reset wire buffer of the element.
void push_back(const Block &element)
Append a sub element.
Buffer::const_iterator end() const
Get end iterator of encoded wire.
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
void encode()
Encode sub elements into TLV-VALUE.
Block blockFromValue() const
Buffer::const_iterator m_end
bool operator==(const Data &lhs, const Data &rhs)
void printHex(std::ostream &os, uint64_t num, bool wantUpperCase)
Output the hex representation of num to the output stream os.
implements an output stream that constructs ndn::Buffer
std::string to_string(const V &v)
bool hasValue() const
Get begin iterator of TLV-VALUE.
Block()
Create an empty Block.
EncodingImpl< EncoderTag > EncodingBuffer
uint32_t type() const
Get TLV-TYPE.
EncodingImpl< EstimatorTag > EncodingEstimator
bool readVarNumber(Iterator &begin, Iterator end, uint64_t &number) noexcept
Read VAR-NUMBER in NDN-TLV encoding.
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM
shared_ptr< const Buffer > ConstBufferPtr