NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
name-component-types.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2022 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
22 #ifndef NDN_CXX_IMPL_NAME_COMPONENT_TYPES_HPP
23 #define NDN_CXX_IMPL_NAME_COMPONENT_TYPES_HPP
24 
26 #include "ndn-cxx/util/sha256.hpp"
28 
29 #include <array>
30 #include <unordered_map>
31 
32 namespace ndn {
33 namespace name {
34 namespace {
35 
38 class ComponentType : noncopyable
39 {
40 public:
41  using Error = Component::Error;
42 
43  virtual
44  ~ComponentType() = default;
45 
48  virtual void
49  check(const Component& comp) const
50  {
51  }
52 
58  virtual std::tuple<bool, Component>
59  getSuccessor(const Component& comp) const
60  {
61  return {false, Component(std::get<Block>(getSuccessorImpl(comp)))};
62  }
63 
66  virtual span<const uint8_t>
67  getMinValue() const
68  {
69  static const std::vector<uint8_t> value;
70  return value;
71  }
72 
82  virtual const char*
83  getAltUriPrefix() const
84  {
85  return nullptr;
86  }
87 
93  virtual Component
94  parseAltUriValue(const std::string&) const
95  {
97  }
98 
104  virtual void
105  writeUri(std::ostream& os, const Component& comp) const
106  {
107  os << comp.type() << '=';
108  writeUriEscapedValue(os, comp);
109  }
110 
111 protected:
116  static std::tuple<bool, Block>
117  getSuccessorImpl(const Component& comp)
118  {
119  EncodingBuffer encoder(comp.size() + 9, 9);
120  // leave room for additional byte when TLV-VALUE overflows, and for TLV-LENGTH size increase
121 
122  bool isOverflow = true;
123  size_t i = comp.value_size();
124  for (; isOverflow && i > 0; i--) {
125  uint8_t newValue = static_cast<uint8_t>((comp.value()[i - 1] + 1) & 0xFF);
126  encoder.prependBytes({newValue});
127  isOverflow = (newValue == 0);
128  }
129  encoder.prependBytes({comp.value(), i});
130 
131  if (isOverflow) {
132  // new name component has to be extended
133  encoder.appendBytes({0});
134  }
135 
136  encoder.prependVarNumber(encoder.size());
137  encoder.prependVarNumber(comp.type());
138  return {isOverflow, encoder.block()};
139  }
140 
144  static void
145  writeUriEscapedValue(std::ostream& os, const Component& comp)
146  {
147  bool isAllPeriods = std::all_of(comp.value_begin(), comp.value_end(),
148  [] (uint8_t x) { return x == '.'; });
149  if (isAllPeriods) {
150  os << "...";
151  }
152  escape(os, reinterpret_cast<const char*>(comp.value()), comp.value_size());
153  }
154 };
155 
161 class GenericNameComponentType final : public ComponentType
162 {
163 public:
164  void
165  writeUri(std::ostream& os, const Component& comp) const final
166  {
167  writeUriEscapedValue(os, comp);
168  }
169 };
170 
174 class Sha256ComponentType final : public ComponentType
175 {
176 public:
177  Sha256ComponentType(uint32_t type, const std::string& typeName, const std::string& uriPrefix)
178  : m_type(type)
179  , m_typeName(typeName)
180  , m_uriPrefix(uriPrefix)
181  {
182  }
183 
184  void
185  check(const Component& comp) const final
186  {
187  BOOST_ASSERT(comp.type() == m_type);
188  if (comp.value_size() != util::Sha256::DIGEST_SIZE) {
189  NDN_THROW(Error(m_typeName + " TLV-LENGTH must be " + to_string(util::Sha256::DIGEST_SIZE)));
190  }
191  }
192 
193  std::tuple<bool, Component>
194  getSuccessor(const Component& comp) const final
195  {
196  bool isExtended = false;
197  Block successor;
198  std::tie(isExtended, successor) = getSuccessorImpl(comp);
199  return {isExtended, isExtended ? comp : Component(successor)};
200  }
201 
202  span<const uint8_t>
203  getMinValue() const final
204  {
205  static const std::vector<uint8_t> value(util::Sha256::DIGEST_SIZE);
206  return value;
207  }
208 
209  const char*
210  getAltUriPrefix() const final
211  {
212  return m_uriPrefix.data();
213  }
214 
215  Component
216  parseAltUriValue(const std::string& input) const final
217  {
218  shared_ptr<Buffer> value;
219  try {
220  value = fromHex(input);
221  }
222  catch (const StringHelperError&) {
223  NDN_THROW(Error("Cannot convert to " + m_typeName + " (invalid hex encoding)"));
224  }
225  return {m_type, std::move(value)};
226  }
227 
228  void
229  writeUri(std::ostream& os, const Component& comp) const final
230  {
231  os << m_uriPrefix << '=';
232  printHex(os, comp.value_bytes(), false);
233  }
234 
235 private:
236  const uint32_t m_type;
237  const std::string m_typeName;
238  const std::string m_uriPrefix;
239 };
240 
244 class DecimalComponentType final : public ComponentType
245 {
246 public:
247  DecimalComponentType(uint32_t type, const std::string& typeName, const std::string& uriPrefix)
248  : m_type(type)
249  , m_typeName(typeName)
250  , m_uriPrefix(uriPrefix)
251  {
252  }
253 
254  // NOTE:
255  // We do not override check() and ensure that the component value is a well-formed
256  // NonNegativeInteger, because the application may be using the same typed component
257  // with different syntax and semantics.
258 
259  const char*
260  getAltUriPrefix() const final
261  {
262  return m_uriPrefix.data();
263  }
264 
265  Component
266  parseAltUriValue(const std::string& input) const final
267  {
268  uint64_t n = 0;
269  try {
270  n = std::stoull(input);
271  }
272  catch (const std::invalid_argument&) {
273  NDN_THROW(Error("Cannot convert to " + m_typeName + " (invalid format)"));
274  }
275  catch (const std::out_of_range&) {
276  NDN_THROW(Error("Cannot convert to " + m_typeName + " (out of range)"));
277  }
278  if (to_string(n) != input) {
279  NDN_THROW(Error("Cannot convert to " + m_typeName + " (invalid format)"));
280  }
281  return Component::fromNumber(n, m_type);
282  }
283 
284  void
285  writeUri(std::ostream& os, const Component& comp) const final
286  {
287  if (comp.isNumber()) {
288  os << m_uriPrefix << '=' << comp.toNumber();
289  }
290  else {
291  ComponentType::writeUri(os, comp);
292  }
293  }
294 
295 private:
296  const uint32_t m_type;
297  const std::string m_typeName;
298  const std::string m_uriPrefix;
299 };
300 
304 class ComponentTypeTable : noncopyable
305 {
306 public:
307  ComponentTypeTable();
308 
312  const ComponentType&
313  get(uint32_t type) const
314  {
315  if (type >= m_table.size() || m_table[type] == nullptr) {
316  return m_baseType;
317  }
318  return *m_table[type];
319  }
320 
324  const ComponentType*
325  findByUriPrefix(const std::string& prefix) const
326  {
327  auto it = m_uriPrefixes.find(prefix);
328  if (it == m_uriPrefixes.end()) {
329  return nullptr;
330  }
331  return it->second;
332  }
333 
334 private:
335  void
336  set(uint32_t type, const ComponentType& ct)
337  {
338  m_table.at(type) = &ct;
339  if (ct.getAltUriPrefix() != nullptr) {
340  m_uriPrefixes[ct.getAltUriPrefix()] = &ct;
341  }
342  }
343 
344 private:
345  const ComponentType m_baseType;
346  std::array<const ComponentType*, 60> m_table;
347  std::unordered_map<std::string, const ComponentType*> m_uriPrefixes;
348 };
349 
350 inline
351 ComponentTypeTable::ComponentTypeTable()
352 {
353  m_table.fill(nullptr);
354 
355  static const Sha256ComponentType ct1(tlv::ImplicitSha256DigestComponent,
356  "ImplicitSha256DigestComponent", "sha256digest");
358  static const Sha256ComponentType ct2(tlv::ParametersSha256DigestComponent,
359  "ParametersSha256DigestComponent", "params-sha256");
361 
362  static const GenericNameComponentType ct8;
363  set(tlv::GenericNameComponent, ct8);
364 
365  static const ComponentType ct32;
366  set(tlv::KeywordNameComponent, ct32);
367 
368  static const DecimalComponentType ct50(tlv::SegmentNameComponent, "SegmentNameComponent", "seg");
369  set(tlv::SegmentNameComponent, ct50);
370  static const DecimalComponentType ct52(tlv::ByteOffsetNameComponent, "ByteOffsetNameComponent", "off");
371  set(tlv::ByteOffsetNameComponent, ct52);
372  static const DecimalComponentType ct54(tlv::VersionNameComponent, "VersionNameComponent", "v");
373  set(tlv::VersionNameComponent, ct54);
374  static const DecimalComponentType ct56(tlv::TimestampNameComponent, "TimestampNameComponent", "t");
375  set(tlv::TimestampNameComponent, ct56);
376  static const DecimalComponentType ct58(tlv::SequenceNumNameComponent, "SequenceNumNameComponent", "seq");
378 }
379 
383 inline const ComponentTypeTable&
384 getComponentTypeTable()
385 {
386  static ComponentTypeTable ctt;
387  return ctt;
388 }
389 
390 } // namespace
391 } // namespace name
392 } // namespace ndn
393 
394 #endif // NDN_CXX_IMPL_NAME_COMPONENT_TYPES_HPP
Copyright (c) 2011-2015 Regents of the University of California.
std::string to_string(const T &val)
Definition: backports.hpp:86
static const size_t DIGEST_SIZE
Length in bytes of a SHA-256 digest.
Definition: sha256.hpp:56
const_iterator value_begin() const noexcept
Get begin iterator of TLV-VALUE.
Definition: block.hpp:301
size_t value_size() const noexcept
Return the size of TLV-VALUE, i.e., the TLV-LENGTH.
Definition: block.hpp:321
Represents a TLV element of the NDN packet format.
Definition: block.hpp:44
#define NDN_THROW(e)
Definition: exception.hpp:61
bool isNumber() const
Check if the component is a NonNegativeInteger.
size_t size() const
Return the size of the encoded wire, i.e., of the whole TLV.
Definition: block.cpp:294
shared_ptr< Buffer > fromHex(const std::string &hexString)
Convert the hex string to buffer.
std::string escape(const std::string &str)
Percent-encode a string.
uint64_t toNumber() const
Interpret this name component as a NonNegativeInteger.
const uint8_t * value() const noexcept
Return a raw pointer to the beginning of TLV-VALUE.
Definition: block.cpp:306
span< const uint8_t > value_bytes() const noexcept
Return a read-only view of TLV-VALUE as a contiguous range of bytes.
Definition: block.hpp:330
Represents a name component.
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition: block.hpp:277
static Component fromNumber(uint64_t number, uint32_t type=tlv::GenericNameComponent)
Create a component encoded as NonNegativeInteger.
#define NDN_CXX_UNREACHABLE
Definition: backports.hpp:138
void printHex(std::ostream &os, uint64_t num, bool wantUpperCase)
Output the hex representation of num to the output stream os.
const_iterator value_end() const noexcept
Get end iterator of TLV-VALUE.
Definition: block.hpp:311
EncodingImpl< EncoderTag > EncodingBuffer