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-2018 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/bind.hpp>
26 #include <boost/mpl/for_each.hpp>
27 #include <boost/range/adaptor/reversed.hpp>
28 
29 namespace ndn {
30 namespace lp {
31 
32 namespace {
33 
34 template<typename TAG>
35 int
36 getLocationSortOrder() noexcept;
37 
38 template<>
39 constexpr int
40 getLocationSortOrder<field_location_tags::Header>() noexcept
41 {
42  return 1;
43 }
44 
45 template<>
46 constexpr int
47 getLocationSortOrder<field_location_tags::Fragment>() noexcept
48 {
49  return 2;
50 }
51 
52 class FieldInfo
53 {
54 public:
55  constexpr
56  FieldInfo() noexcept = default;
57 
58  explicit
59  FieldInfo(uint64_t tlv) noexcept;
60 
61 public:
62  uint64_t tlvType = 0;
63  bool isRecognized = false;
64  bool canIgnore = false;
65  bool isRepeatable = false;
66  int locationSortOrder = getLocationSortOrder<field_location_tags::Header>();
67 };
68 
69 class ExtractFieldInfo
70 {
71 public:
72  using result_type = void;
73 
74  template<typename T>
75  constexpr void
76  operator()(FieldInfo* info, const T&) const noexcept
77  {
78  if (T::TlvType::value != info->tlvType) {
79  return;
80  }
81  info->isRecognized = true;
82  info->canIgnore = false;
83  info->isRepeatable = T::IsRepeatable::value;
84  info->locationSortOrder = getLocationSortOrder<typename T::FieldLocation>();
85  }
86 };
87 
88 FieldInfo::FieldInfo(uint64_t tlv) noexcept
89  : tlvType(tlv)
90 {
91  boost::mpl::for_each<FieldSet>(boost::bind(ExtractFieldInfo(), this, _1));
92  if (!isRecognized) {
95  (tlvType & 0x03) == 0x00;
96  }
97 }
98 
99 constexpr bool
100 compareFieldSortOrder(const FieldInfo& first, const FieldInfo& second) noexcept
101 {
102  return (first.locationSortOrder < second.locationSortOrder) ||
103  (first.locationSortOrder == second.locationSortOrder && first.tlvType < second.tlvType);
104 }
105 
106 } // namespace
107 
109  : m_wire(Block(tlv::LpPacket))
110 {
111 }
112 
113 Packet::Packet(const Block& wire)
114 {
115  wireDecode(wire);
116 }
117 
118 Block
120 {
121  // If no header or trailer, return bare network packet
122  Block::element_container elements = m_wire.elements();
123  if (elements.size() == 1 && elements.front().type() == FragmentField::TlvType::value) {
124  elements.front().parse();
125  return elements.front().elements().front();
126  }
127 
128  m_wire.encode();
129  return m_wire;
130 }
131 
132 void
134 {
135  if (wire.type() == ndn::tlv::Interest || wire.type() == ndn::tlv::Data) {
136  m_wire = Block(tlv::LpPacket);
137  add<FragmentField>(make_pair(wire.begin(), wire.end()));
138  return;
139  }
140 
141  if (wire.type() != tlv::LpPacket) {
142  BOOST_THROW_EXCEPTION(Error("unrecognized TLV-TYPE " + to_string(wire.type())));
143  }
144 
145  wire.parse();
146 
147  bool isFirst = true;
148  FieldInfo prev;
149  for (const Block& element : wire.elements()) {
150  FieldInfo info(element.type());
151 
152  if (!info.isRecognized && !info.canIgnore) {
153  BOOST_THROW_EXCEPTION(Error("unrecognized field " + to_string(element.type()) + " cannot be ignored"));
154  }
155 
156  if (!isFirst) {
157  if (info.tlvType == prev.tlvType && !info.isRepeatable) {
158  BOOST_THROW_EXCEPTION(Error("non-repeatable field " + to_string(element.type()) + " cannot be repeated"));
159  }
160 
161  else if (info.tlvType != prev.tlvType && !compareFieldSortOrder(prev, info)) {
162  BOOST_THROW_EXCEPTION(Error("fields are not in correct sort order"));
163  }
164  }
165 
166  isFirst = false;
167  prev = info;
168  }
169 
170  m_wire = wire;
171 }
172 
173 bool
174 Packet::comparePos(uint64_t first, const Block& second) noexcept
175 {
176  FieldInfo firstInfo(first);
177  FieldInfo secondInfo(second.type());
178  return compareFieldSortOrder(firstInfo, secondInfo);
179 }
180 
181 } // namespace lp
182 } // namespace ndn
Definition: data.cpp:26
const element_container & elements() const
Get container of sub elements.
Definition: block.hpp:361
Buffer::const_iterator end() const
Get end iterator of encoded wire.
Definition: block.cpp:280
lower bound of 3-octet header field
Definition: tlv.hpp:65
bool canIgnore
can this unknown field be ignored
Definition: packet.cpp:64
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
void wireDecode(const Block &wire)
decode packet from wire format
Definition: packet.cpp:133
bool isRecognized
is this field known
Definition: packet.cpp:63
bool isRepeatable
is the field repeatable
Definition: packet.cpp:65
Block wireEncode() const
encode packet into wire format
Definition: packet.cpp:119
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:333
uint32_t type() const
Get TLV-TYPE.
Definition: block.hpp:249
uint64_t tlvType
TLV-TYPE of the field; 0 if field does not exist.
Definition: packet.cpp:62
void encode()
Encode sub elements into TLV-VALUE.
Definition: block.cpp:361
std::string to_string(const V &v)
Definition: backports.hpp:67
upper bound of 3-octet header field
Definition: tlv.hpp:70
int locationSortOrder
sort order of field_location_tag
Definition: packet.cpp:66
std::vector< Block > element_container
Definition: block.hpp:45
Buffer::const_iterator begin() const
Get begin iterator of encoded wire.
Definition: block.cpp:271