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