blob: 07ec2f07cca2778f72a88f0963fc269d79f4e718 [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 *
5 * BSD license, See the LICENSE file for more information
6 *
7 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
8 */
9
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080010#include "common.hpp"
11
12#include "block.hpp"
13#include "tlv.hpp"
Alexander Afanasyev15151312014-02-16 00:53:51 -080014#include "encoding-buffer.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080015
16namespace ndn {
17
18Block::Block()
19 : m_type(std::numeric_limits<uint32_t>::max())
20{
21}
22
Alexander Afanasyev15151312014-02-16 00:53:51 -080023Block::Block(const EncodingBuffer& buffer)
24 : m_buffer(buffer.m_buffer)
25 , m_begin(buffer.begin())
26 , m_end(buffer.end())
27 , m_size(m_end - m_begin)
28{
29 m_value_begin = m_begin;
30 m_value_end = m_end;
31
32 m_type = Tlv::readType(m_value_begin, m_value_end);
33 uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
34 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
35 {
36 throw Tlv::Error("TLV length doesn't match buffer length");
37 }
38}
39
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080040Block::Block(const ConstBufferPtr &wire,
41 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080042 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
43 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080044 : m_buffer(wire)
45 , m_type(type)
46 , m_begin(begin)
47 , m_end(end)
48 , m_size(m_end - m_begin)
49 , m_value_begin(valueBegin)
50 , m_value_end(valueEnd)
51{
52}
53
54Block::Block(const ConstBufferPtr &buffer)
55 : m_buffer(buffer)
56 , m_begin(m_buffer->begin())
57 , m_end(m_buffer->end())
58 , m_size(m_end - m_begin)
59{
Alexander Afanasyev233750e2014-02-16 00:50:07 -080060 m_value_begin = m_begin;
61 m_value_end = m_end;
Alexander Afanasyev937aa782014-03-21 13:17:57 -070062
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080063 m_type = Tlv::readType(m_value_begin, m_value_end);
64
65 uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -080066 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080067 {
68 throw Tlv::Error("TLV length doesn't match buffer length");
69 }
70}
71
Alexander Afanasyev187bc482014-02-06 15:04:04 -080072Block::Block(const ConstBufferPtr &buffer,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080073 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
74 bool verifyLength/* = true*/)
Alexander Afanasyev187bc482014-02-06 15:04:04 -080075 : m_buffer(buffer)
76 , m_begin(begin)
77 , m_end(end)
Alexander Afanasyev380420b2014-02-09 20:52:29 -080078 , m_size(m_end - m_begin)
Alexander Afanasyev187bc482014-02-06 15:04:04 -080079{
Alexander Afanasyev233750e2014-02-16 00:50:07 -080080 m_value_begin = m_begin;
81 m_value_end = m_end;
Alexander Afanasyev380420b2014-02-09 20:52:29 -080082
Alexander Afanasyev187bc482014-02-06 15:04:04 -080083 m_type = Tlv::readType(m_value_begin, m_value_end);
Alexander Afanasyev63ab0842014-03-19 18:39:31 -070084 uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080085 if (verifyLength)
Alexander Afanasyev187bc482014-02-06 15:04:04 -080086 {
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080087 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
88 {
89 throw Tlv::Error("TLV length doesn't match buffer length");
90 }
Alexander Afanasyev187bc482014-02-06 15:04:04 -080091 }
92}
93
Yingdi Yu27158392014-01-20 13:04:20 -080094Block::Block(std::istream& is)
95{
Alexander Afanasyev937aa782014-03-21 13:17:57 -070096 std::istream_iterator<uint8_t> tmp_begin(is);
Yingdi Yu27158392014-01-20 13:04:20 -080097 std::istream_iterator<uint8_t> tmp_end;
Alexander Afanasyev937aa782014-03-21 13:17:57 -070098
Yingdi Yu27158392014-01-20 13:04:20 -080099 m_type = Tlv::readType(tmp_begin, tmp_end);
100 uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
101
102 // We may still have some problem here, if some exception happens in this constructor, we may completely lose all the bytes extracted from the stream.
103
104 OBufferStream os;
105 size_t headerLength = Tlv::writeVarNumber(os, m_type);
106 headerLength += Tlv::writeVarNumber(os, length);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700107
Yingdi Yu27158392014-01-20 13:04:20 -0800108 char* buf = new char[length];
109 buf[0] = *tmp_begin;
110 is.read(buf+1, length-1);
111
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800112 if(length != static_cast<uint64_t>(is.gcount())+1)
Yingdi Yu27158392014-01-20 13:04:20 -0800113 {
114 delete [] buf;
115 throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700116 }
Yingdi Yu27158392014-01-20 13:04:20 -0800117
118 os.write(buf, length);
119 delete [] buf;
120
121 m_buffer = os.buf();
122
123 m_begin = m_buffer->begin();
124 m_end = m_buffer->end();
125 m_size = m_end - m_begin;
126
127 m_value_begin = m_buffer->begin() + headerLength;
128 m_value_end = m_buffer->end();
129}
130
131
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800132Block::Block(const uint8_t *buffer, size_t maxlength)
133{
134 const uint8_t * tmp_begin = buffer;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700135 const uint8_t * tmp_end = buffer + maxlength;
136
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
145 m_buffer = ptr_lib::make_shared<Buffer> (buffer, (tmp_begin - buffer) + length);
146
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(const void *bufferX, size_t maxlength)
156{
157 const uint8_t * buffer = reinterpret_cast<const uint8_t*>(bufferX);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700158
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800159 const uint8_t * tmp_begin = buffer;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700160 const uint8_t * tmp_end = buffer + maxlength;
161
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800162 m_type = Tlv::readType(tmp_begin, tmp_end);
163 uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700164
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800165 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800166 {
167 throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
168 }
169
170 m_buffer = ptr_lib::make_shared<Buffer> (buffer, (tmp_begin - buffer) + length);
171
172 m_begin = m_buffer->begin();
173 m_end = m_buffer->end();
174 m_size = m_end - m_begin;
175
176 m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
177 m_value_end = m_buffer->end();
178}
179
180Block::Block(uint32_t type)
181 : m_type(type)
182{
183}
184
185Block::Block(uint32_t type, const ConstBufferPtr &value)
186 : m_buffer(value)
187 , m_type(type)
188 , m_begin(m_buffer->end())
189 , m_end(m_buffer->end())
190 , m_value_begin(m_buffer->begin())
191 , m_value_end(m_buffer->end())
192{
193 m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
194}
195
196Block::Block(uint32_t type, const Block &value)
197 : m_buffer(value.m_buffer)
198 , m_type(type)
199 , m_begin(m_buffer->end())
200 , m_end(m_buffer->end())
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800201 , m_value_begin(value.begin())
202 , m_value_end(value.end())
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800203{
204 m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
205}
206
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700207bool
208Block::fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block)
209{
210 Buffer::const_iterator tempBegin = wire->begin() + offset;
211
212 uint32_t type;
213 bool ok = Tlv::readType(tempBegin, wire->end(), type);
214 if (!ok)
215 return false;
216
217 uint64_t length;
218 ok = Tlv::readVarNumber(tempBegin, wire->end(), length);
219 if (!ok)
220 return false;
221
222 if (length > static_cast<uint64_t>(wire->end() - tempBegin))
223 {
224 return false;
225 }
226
227 block = Block(wire, type,
228 wire->begin() + offset, tempBegin + length,
229 tempBegin, tempBegin + length);
230
231 return true;
232}
233
234bool
235Block::fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block)
236{
237 const uint8_t* tempBegin = buffer;
238 const uint8_t* tempEnd = buffer + maxSize;
239
240 uint32_t type;
241 bool ok = Tlv::readType(tempBegin, tempEnd, type);
242 if (!ok)
243 return false;
244
245 uint64_t length;
246 ok = Tlv::readVarNumber(tempBegin, tempEnd, length);
247 if (!ok)
248 return false;
249
250 if (length > static_cast<uint64_t>(tempEnd - tempBegin))
251 {
252 return false;
253 }
254
255 BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
256 block = Block(sharedBuffer, type,
257 sharedBuffer->begin(), sharedBuffer->end(),
258 sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end());
259
260 return true;
261}
262
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800263void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800264Block::parse() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800265{
266 if (!m_subBlocks.empty() || value_size()==0)
267 return;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700268
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800269 Buffer::const_iterator begin = value_begin(),
270 end = value_end();
271
272 while (begin != end)
273 {
274 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700275
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800276 uint32_t type = Tlv::readType(begin, end);
277 uint64_t length = Tlv::readVarNumber(begin, end);
278
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800279 if (length > static_cast<uint64_t>(end - begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800280 {
281 m_subBlocks.clear();
282 throw Tlv::Error("TLV length exceeds buffer length");
283 }
284 Buffer::const_iterator element_end = begin + length;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700285
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800286 m_subBlocks.push_back(Block(m_buffer,
287 type,
288 element_begin, element_end,
289 begin, element_end));
290
291 begin = element_end;
292 // don't do recursive parsing, just the top level
293 }
294}
295
296void
297Block::encode()
298{
299 if (hasWire())
300 return;
301
302 OBufferStream os;
303 Tlv::writeVarNumber(os, type());
304
305 if (hasValue())
306 {
307 Tlv::writeVarNumber(os, value_size());
308 os.write(reinterpret_cast<const char*>(value()), value_size());
309 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800310 else if (m_subBlocks.size() == 0)
311 {
312 Tlv::writeVarNumber(os, 0);
313 }
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800314 else
315 {
316 size_t valueSize = 0;
317 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
318 valueSize += i->size();
319 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700320
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800321 Tlv::writeVarNumber(os, valueSize);
322
323 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
324 if (i->hasWire())
325 os.write(reinterpret_cast<const char*>(i->wire()), i->size());
326 else if (i->hasValue()) {
327 Tlv::writeVarNumber(os, i->type());
328 Tlv::writeVarNumber(os, i->value_size());
329 os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
330 }
331 else
332 throw Error("Underlying value buffer is empty");
333 }
334 }
335
336 // now assign correct block
337
338 m_buffer = os.buf();
339 m_begin = m_buffer->begin();
340 m_end = m_buffer->end();
341 m_size = m_end - m_begin;
342
343 m_value_begin = m_buffer->begin();
344 m_value_end = m_buffer->end();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700345
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800346 Tlv::readType(m_value_begin, m_value_end);
347 Tlv::readVarNumber(m_value_begin, m_value_end);
348}
349
Yingdi Yu4270f202014-01-28 14:19:16 -0800350Block
351Block::blockFromValue() const
352{
353 if (value_size()==0)
354 throw Error("Underlying value buffer is empty");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700355
Yingdi Yu4270f202014-01-28 14:19:16 -0800356 Buffer::const_iterator begin = value_begin(),
357 end = value_end();
358
359 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700360
Yingdi Yu4270f202014-01-28 14:19:16 -0800361 uint32_t type = Tlv::readType(begin, end);
362 uint64_t length = Tlv::readVarNumber(begin, end);
363
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800364 if (length != static_cast<uint64_t>(end - begin))
Yingdi Yu4270f202014-01-28 14:19:16 -0800365 throw Tlv::Error("TLV length mismatches buffer length");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700366
Yingdi Yu4270f202014-01-28 14:19:16 -0800367 return Block(m_buffer,
368 type,
369 element_begin, end,
370 begin, end);
371}
372
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800373} // namespace ndn