packet.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2023 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 #include "ndn-cxx/lp/packet.hpp"
23 #include "ndn-cxx/lp/fields.hpp"
24 
25 #include <boost/mp11/algorithm.hpp>
26 
27 namespace ndn::lp {
28 
29 namespace {
30 
31 template<typename Tag>
32 constexpr int8_t
33 getLocationSortOrder() noexcept
34 {
35  if constexpr (std::is_same_v<Tag, field_location_tags::Header>)
36  return 1;
37  if constexpr (std::is_same_v<Tag, field_location_tags::Fragment>)
38  return 2;
39 }
40 
41 struct FieldInfo
42 {
43  constexpr
44  FieldInfo() noexcept = default;
45 
46  explicit
47  FieldInfo(uint32_t type) noexcept;
48 
49  uint32_t tlvType = 0;
50  bool isRecognized = false;
51  bool canIgnore = false;
52  bool isRepeatable = false;
53  int8_t locationSortOrder = getLocationSortOrder<field_location_tags::Header>();
54 };
55 
56 FieldInfo::FieldInfo(uint32_t type) noexcept
57  : tlvType(type)
58 {
59  boost::mp11::mp_for_each<FieldSet>([this] (auto fieldDecl) {
60  if (tlvType == decltype(fieldDecl)::TlvType::value) {
61  isRecognized = true;
62  isRepeatable = decltype(fieldDecl)::IsRepeatable::value;
63  locationSortOrder = getLocationSortOrder<typename decltype(fieldDecl)::FieldLocation>();
64  }
65  });
66 
67  if (!isRecognized) {
70  (tlvType & 0x03) == 0x00;
71  }
72 }
73 
74 constexpr bool
75 compareFieldSortOrder(const FieldInfo& first, const FieldInfo& second) noexcept
76 {
77  return (first.locationSortOrder < second.locationSortOrder) ||
78  (first.locationSortOrder == second.locationSortOrder && first.tlvType < second.tlvType);
79 }
80 
81 } // namespace
82 
83 Packet::Packet() = default;
84 
85 Packet::Packet(const Block& wire)
86 {
87  wireDecode(wire);
88 }
89 
90 Block
92 {
93  // If no header or trailer, return bare network packet
94  auto elements = m_wire.elements();
95  if (elements.size() == 1 && elements.front().type() == FragmentField::TlvType::value) {
96  elements.front().parse();
97  return elements.front().elements().front();
98  }
99 
100  m_wire.encode();
101  return m_wire;
102 }
103 
104 void
106 {
107  if (wire.type() == ndn::tlv::Interest || wire.type() == ndn::tlv::Data) {
108  m_wire = Block(tlv::LpPacket);
109  add<FragmentField>({wire.begin(), wire.end()});
110  return;
111  }
112 
113  if (wire.type() != tlv::LpPacket) {
114  NDN_THROW(Error("LpPacket", wire.type()));
115  }
116 
117  wire.parse();
118 
119  bool isFirst = true;
120  FieldInfo prev;
121  for (const Block& element : wire.elements()) {
122  FieldInfo info(element.type());
123 
124  if (!info.isRecognized && !info.canIgnore) {
125  NDN_THROW(Error("unrecognized field " + to_string(element.type()) + " cannot be ignored"));
126  }
127 
128  if (!isFirst) {
129  if (info.tlvType == prev.tlvType && !info.isRepeatable) {
130  NDN_THROW(Error("non-repeatable field " + to_string(element.type()) + " cannot be repeated"));
131  }
132 
133  else if (info.tlvType != prev.tlvType && !compareFieldSortOrder(prev, info)) {
134  NDN_THROW(Error("fields are not in correct sort order"));
135  }
136  }
137 
138  isFirst = false;
139  prev = info;
140  }
141 
142  m_wire = wire;
143 }
144 
145 bool
146 Packet::comparePos(uint32_t first, const Block& second) noexcept
147 {
148  return compareFieldSortOrder(FieldInfo(first), FieldInfo(second.type()));
149 }
150 
151 } // namespace ndn::lp
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
const_iterator begin() const
Returns an iterator to the beginning of the encoded wire.
Definition: block.cpp:275
const element_container & elements() const noexcept
Get container of sub-elements.
Definition: block.hpp:424
void encode()
Encode sub-elements into TLV-VALUE.
Definition: block.cpp:353
const_iterator end() const
Returns an iterator past-the-end of the encoded wire.
Definition: block.cpp:284
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition: block.hpp:275
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:326
Block wireEncode() const
Encode packet into wire format.
Definition: packet.cpp:91
void wireDecode(const Block &wire)
Decode packet from wire format.
Definition: packet.cpp:105
#define NDN_THROW(e)
Definition: exception.hpp:56
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:30
@ LpPacket
Definition: tlv.hpp:37
@ HEADER3_MAX
Upper bound of 3-octet header field.
Definition: tlv.hpp:70
@ HEADER3_MIN
Lower bound of 3-octet header field.
Definition: tlv.hpp:66
Contains classes and functions related to NDNLPv2.
@ Data
Definition: tlv.hpp:69
@ Interest
Definition: tlv.hpp:68
bool isRecognized
is this field known
Definition: packet.cpp:50
uint32_t tlvType
TLV-TYPE of the field; 0 if field does not exist.
Definition: packet.cpp:49
bool canIgnore
can this unknown field be ignored
Definition: packet.cpp:51
int8_t locationSortOrder
sort order of field_location_tag
Definition: packet.cpp:53
bool isRepeatable
is the field repeatable
Definition: packet.cpp:52
SignatureInfo info