blob: 3f0cee397358561e9662d566f31743245fc2dfe8 [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
3 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08005 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08008 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07009 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080013 */
14
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080015#include "common.hpp"
16
17#include "block.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070018#include "block-helpers.hpp"
19
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080020#include "tlv.hpp"
Alexander Afanasyev15151312014-02-16 00:53:51 -080021#include "encoding-buffer.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070022#include "buffer-stream.hpp"
23
24#include <boost/lexical_cast.hpp>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080025
26namespace ndn {
27
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070028const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM = 8800;
29
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080030Block::Block()
31 : m_type(std::numeric_limits<uint32_t>::max())
32{
33}
34
Alexander Afanasyev15151312014-02-16 00:53:51 -080035Block::Block(const EncodingBuffer& buffer)
36 : m_buffer(buffer.m_buffer)
37 , m_begin(buffer.begin())
38 , m_end(buffer.end())
39 , m_size(m_end - m_begin)
40{
41 m_value_begin = m_begin;
42 m_value_end = m_end;
43
44 m_type = Tlv::readType(m_value_begin, m_value_end);
45 uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
46 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
47 {
48 throw Tlv::Error("TLV length doesn't match buffer length");
49 }
50}
51
Alexander Afanasyeva465e972014-03-22 17:21:49 -070052Block::Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080053 uint32_t type,
Alexander Afanasyeva465e972014-03-22 17:21:49 -070054 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
55 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080056 : m_buffer(wire)
57 , m_type(type)
58 , m_begin(begin)
59 , m_end(end)
60 , m_size(m_end - m_begin)
61 , m_value_begin(valueBegin)
62 , m_value_end(valueEnd)
63{
64}
65
Alexander Afanasyeva465e972014-03-22 17:21:49 -070066Block::Block(const ConstBufferPtr& buffer)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080067 : m_buffer(buffer)
68 , m_begin(m_buffer->begin())
69 , m_end(m_buffer->end())
70 , m_size(m_end - m_begin)
71{
Alexander Afanasyev233750e2014-02-16 00:50:07 -080072 m_value_begin = m_begin;
73 m_value_end = m_end;
Alexander Afanasyev937aa782014-03-21 13:17:57 -070074
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080075 m_type = Tlv::readType(m_value_begin, m_value_end);
76
77 uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -080078 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080079 {
80 throw Tlv::Error("TLV length doesn't match buffer length");
81 }
82}
83
Alexander Afanasyeva465e972014-03-22 17:21:49 -070084Block::Block(const ConstBufferPtr& buffer,
85 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080086 bool verifyLength/* = true*/)
Alexander Afanasyev187bc482014-02-06 15:04:04 -080087 : m_buffer(buffer)
88 , m_begin(begin)
89 , m_end(end)
Alexander Afanasyev380420b2014-02-09 20:52:29 -080090 , m_size(m_end - m_begin)
Alexander Afanasyev187bc482014-02-06 15:04:04 -080091{
Alexander Afanasyev233750e2014-02-16 00:50:07 -080092 m_value_begin = m_begin;
93 m_value_end = m_end;
Alexander Afanasyev380420b2014-02-09 20:52:29 -080094
Alexander Afanasyev187bc482014-02-06 15:04:04 -080095 m_type = Tlv::readType(m_value_begin, m_value_end);
Alexander Afanasyev63ab0842014-03-19 18:39:31 -070096 uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080097 if (verifyLength)
Alexander Afanasyev187bc482014-02-06 15:04:04 -080098 {
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080099 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
100 {
101 throw Tlv::Error("TLV length doesn't match buffer length");
102 }
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800103 }
104}
105
Yingdi Yu27158392014-01-20 13:04:20 -0800106
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700107Block::Block(const uint8_t* buffer, size_t maxlength)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800108{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700109 const uint8_t* tmp_begin = buffer;
110 const uint8_t* tmp_end = buffer + maxlength;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700111
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800112 m_type = Tlv::readType(tmp_begin, tmp_end);
113 uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700114
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800115 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800116 {
117 throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
118 }
119
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700120 m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800121
122 m_begin = m_buffer->begin();
123 m_end = m_buffer->end();
124 m_size = m_end - m_begin;
125
126 m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
127 m_value_end = m_buffer->end();
128}
129
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700130Block::Block(const void* bufferX, size_t maxlength)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800131{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700132 const uint8_t* buffer = reinterpret_cast<const uint8_t*>(bufferX);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700133
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700134 const uint8_t* tmp_begin = buffer;
135 const uint8_t* tmp_end = buffer + maxlength;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700136
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800137 m_type = Tlv::readType(tmp_begin, tmp_end);
138 uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700139
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800140 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800141 {
142 throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
143 }
144
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700145 m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800146
147 m_begin = m_buffer->begin();
148 m_end = m_buffer->end();
149 m_size = m_end - m_begin;
150
151 m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
152 m_value_end = m_buffer->end();
153}
154
155Block::Block(uint32_t type)
156 : m_type(type)
157{
158}
159
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700160Block::Block(uint32_t type, const ConstBufferPtr& value)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800161 : m_buffer(value)
162 , m_type(type)
163 , m_begin(m_buffer->end())
164 , m_end(m_buffer->end())
165 , m_value_begin(m_buffer->begin())
166 , m_value_end(m_buffer->end())
167{
168 m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
169}
170
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700171Block::Block(uint32_t type, const Block& value)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800172 : m_buffer(value.m_buffer)
173 , m_type(type)
174 , m_begin(m_buffer->end())
175 , m_end(m_buffer->end())
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800176 , m_value_begin(value.begin())
177 , m_value_end(value.end())
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800178{
179 m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
180}
181
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700182Block
183Block::fromStream(std::istream& is)
184{
185 std::istream_iterator<uint8_t> tmp_begin(is);
186 std::istream_iterator<uint8_t> tmp_end;
187
188 uint32_t type = Tlv::readType(tmp_begin, tmp_end);
189 uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
190
191 if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM)
192 throw Tlv::Error("Length of block from stream is too large");
193
194 // We may still have some problem here, if some exception happens,
195 // we may completely lose all the bytes extracted from the stream.
196
197 char buf[MAX_SIZE_OF_BLOCK_FROM_STREAM];
198 buf[0] = *tmp_begin;
199 is.read(buf+1, length-1);
200
201 if (length != static_cast<uint64_t>(is.gcount()) + 1) {
202 throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
203 }
204
205 return dataBlock(type, buf, length);
206}
207
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700208bool
209Block::fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block)
210{
211 Buffer::const_iterator tempBegin = wire->begin() + offset;
212
213 uint32_t type;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700214 bool isOk = Tlv::readType(tempBegin, wire->end(), type);
215 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700216 return false;
217
218 uint64_t length;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700219 isOk = Tlv::readVarNumber(tempBegin, wire->end(), length);
220 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700221 return false;
222
223 if (length > static_cast<uint64_t>(wire->end() - tempBegin))
224 {
225 return false;
226 }
227
228 block = Block(wire, type,
229 wire->begin() + offset, tempBegin + length,
230 tempBegin, tempBegin + length);
231
232 return true;
233}
234
235bool
236Block::fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block)
237{
238 const uint8_t* tempBegin = buffer;
239 const uint8_t* tempEnd = buffer + maxSize;
240
Mickey Sweatt632e0572014-04-20 00:36:32 -0700241 uint32_t type = 0;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700242 bool isOk = Tlv::readType(tempBegin, tempEnd, type);
243 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700244 return false;
245
246 uint64_t length;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700247 isOk = Tlv::readVarNumber(tempBegin, tempEnd, length);
248 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700249 return false;
250
251 if (length > static_cast<uint64_t>(tempEnd - tempBegin))
252 {
253 return false;
254 }
255
256 BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
257 block = Block(sharedBuffer, type,
258 sharedBuffer->begin(), sharedBuffer->end(),
259 sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end());
260
261 return true;
262}
263
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800264void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800265Block::parse() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800266{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700267 if (!m_subBlocks.empty() || value_size() == 0)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800268 return;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700269
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700270 Buffer::const_iterator begin = value_begin();
271 Buffer::const_iterator end = value_end();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800272
273 while (begin != end)
274 {
275 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700276
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800277 uint32_t type = Tlv::readType(begin, end);
278 uint64_t length = Tlv::readVarNumber(begin, end);
279
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800280 if (length > static_cast<uint64_t>(end - begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800281 {
282 m_subBlocks.clear();
283 throw Tlv::Error("TLV length exceeds buffer length");
284 }
285 Buffer::const_iterator element_end = begin + length;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700286
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800287 m_subBlocks.push_back(Block(m_buffer,
288 type,
289 element_begin, element_end,
290 begin, element_end));
291
292 begin = element_end;
293 // don't do recursive parsing, just the top level
294 }
295}
296
297void
298Block::encode()
299{
300 if (hasWire())
301 return;
302
303 OBufferStream os;
304 Tlv::writeVarNumber(os, type());
305
306 if (hasValue())
307 {
308 Tlv::writeVarNumber(os, value_size());
309 os.write(reinterpret_cast<const char*>(value()), value_size());
310 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800311 else if (m_subBlocks.size() == 0)
312 {
313 Tlv::writeVarNumber(os, 0);
314 }
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800315 else
316 {
317 size_t valueSize = 0;
318 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
319 valueSize += i->size();
320 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700321
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800322 Tlv::writeVarNumber(os, valueSize);
323
324 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
325 if (i->hasWire())
326 os.write(reinterpret_cast<const char*>(i->wire()), i->size());
327 else if (i->hasValue()) {
328 Tlv::writeVarNumber(os, i->type());
329 Tlv::writeVarNumber(os, i->value_size());
330 os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
331 }
332 else
333 throw Error("Underlying value buffer is empty");
334 }
335 }
336
337 // now assign correct block
338
339 m_buffer = os.buf();
340 m_begin = m_buffer->begin();
341 m_end = m_buffer->end();
342 m_size = m_end - m_begin;
343
344 m_value_begin = m_buffer->begin();
345 m_value_end = m_buffer->end();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700346
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800347 Tlv::readType(m_value_begin, m_value_end);
348 Tlv::readVarNumber(m_value_begin, m_value_end);
349}
350
Yingdi Yu4270f202014-01-28 14:19:16 -0800351Block
352Block::blockFromValue() const
353{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700354 if (value_size() == 0)
Yingdi Yu4270f202014-01-28 14:19:16 -0800355 throw Error("Underlying value buffer is empty");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700356
Yingdi Yu4270f202014-01-28 14:19:16 -0800357 Buffer::const_iterator begin = value_begin(),
358 end = value_end();
359
360 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700361
Yingdi Yu4270f202014-01-28 14:19:16 -0800362 uint32_t type = Tlv::readType(begin, end);
363 uint64_t length = Tlv::readVarNumber(begin, end);
364
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800365 if (length != static_cast<uint64_t>(end - begin))
Yingdi Yu4270f202014-01-28 14:19:16 -0800366 throw Tlv::Error("TLV length mismatches buffer length");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700367
Yingdi Yu4270f202014-01-28 14:19:16 -0800368 return Block(m_buffer,
369 type,
370 element_begin, end,
371 begin, end);
372}
373
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700374const Block&
375Block::get(uint32_t type) const
376{
377 for (element_const_iterator i = m_subBlocks.begin();
378 i != m_subBlocks.end();
379 i++)
380 {
381 if (i->type() == type)
382 {
383 return *i;
384 }
385 }
386
387 throw Error("(Block::get) Requested a non-existed type [" +
388 boost::lexical_cast<std::string>(type) + "] from Block");
389}
390
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800391} // namespace ndn