prefix-announcement.cpp
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 
24 
25 namespace ndn {
26 
27 static_assert(std::is_base_of<tlv::Error, PrefixAnnouncement::Error>::value,
28  "PrefixAnnouncement::Error must inherit from tlv::Error");
29 
31 
33  : m_data(std::move(data))
34 {
35  const Name& dataName = m_data->getName();
36  if (dataName.size() < 3 || dataName[-3] != getKeywordComponent() ||
37  !dataName[-2].isVersion() || !dataName[-1].isSegment()) {
38  NDN_THROW(Error("Data is not a prefix announcement: wrong name structure"));
39  }
40  m_announcedName = dataName.getPrefix(-3);
41 
42  if (m_data->getContentType() != tlv::ContentType_PrefixAnn) {
43  NDN_THROW(Error("Data is not a prefix announcement: ContentType is " +
44  to_string(m_data->getContentType())));
45  }
46 
47  if (m_data->getContent().value_size() == 0) {
48  NDN_THROW(Error("Prefix announcement is empty"));
49  }
50 
51  const Block& payload = m_data->getContent();
52  payload.parse();
53 
55 
56  auto validityElement = payload.find(tlv::ValidityPeriod);
57  if (validityElement != payload.elements_end()) {
58  m_validity.emplace(*validityElement);
59  }
60 
61  for (const Block& element : payload.elements()) {
62  if (element.type() != tlv::nfd::ExpirationPeriod && element.type() != tlv::ValidityPeriod &&
63  tlv::isCriticalType(element.type())) {
64  NDN_THROW(Error("Unrecognized element of critical type " + to_string(element.type())));
65  }
66  }
67 }
68 
69 const Data&
71  optional<uint64_t> version) const
72 {
73  if (!m_data) {
74  Name dataName = m_announcedName;
75  dataName.append(getKeywordComponent())
76  .appendVersion(version.value_or(time::toUnixTimestamp(time::system_clock::now()).count()))
77  .appendSegment(0);
78  m_data.emplace(dataName);
79  m_data->setContentType(tlv::ContentType_PrefixAnn);
80 
81  Block content(tlv::Content);
83  m_expiration.count()));
84  if (m_validity) {
85  content.push_back(m_validity->wireEncode());
86  }
87  content.encode();
88  m_data->setContent(content);
89 
90  keyChain.sign(*m_data, si);
91  }
92  return *m_data;
93 }
94 
97 {
98  m_data.reset();
99  m_announcedName = std::move(name);
100  return *this;
101 }
102 
105 {
106  if (expiration < 0_ms) {
107  NDN_THROW(std::invalid_argument("expiration period is negative"));
108  }
109  m_data.reset();
110  m_expiration = expiration;
111  return *this;
112 }
113 
115 PrefixAnnouncement::setValidityPeriod(optional<security::ValidityPeriod> validity)
116 {
117  m_data.reset();
118  m_validity = std::move(validity);
119  return *this;
120 }
121 
122 const name::Component&
124 {
125  static const name::Component nc(tlv::KeywordNameComponent, {'P', 'A'});
126  return nc;
127 }
128 
129 bool
131 {
132  return lhs.getAnnouncedName() == rhs.getAnnouncedName() &&
133  lhs.getExpiration() == rhs.getExpiration() &&
134  lhs.getValidityPeriod() == rhs.getValidityPeriod();
135 }
136 
137 std::ostream&
138 operator<<(std::ostream& os, const PrefixAnnouncement& pa)
139 {
140  os << pa.getAnnouncedName() << " expires=" << pa.getExpiration();
141  if (pa.getValidityPeriod()) {
142  os << " validity=" << *pa.getValidityPeriod();
143  }
144  return os;
145 }
146 
147 } // namespace ndn
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
element_const_iterator find(uint32_t type) const
Find the first sub-element of the specified TLV-TYPE.
Definition: block.cpp:424
const element_container & elements() const noexcept
Get container of sub-elements.
Definition: block.hpp:426
element_const_iterator elements_end() const noexcept
Equivalent to elements().end().
Definition: block.hpp:444
void push_back(const Block &element)
Append a sub-element.
Definition: block.cpp:455
void encode()
Encode sub-elements into TLV-VALUE.
Definition: block.cpp:351
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:324
const Block & get(uint32_t type) const
Return the first sub-element of the specified TLV-TYPE.
Definition: block.cpp:412
Represents a Data packet.
Definition: data.hpp:39
Represents an absolute name.
Definition: name.hpp:44
PartialName getPrefix(ssize_t nComponents) const
Returns a prefix of the name.
Definition: name.hpp:216
Name & appendSegment(uint64_t segmentNo)
Append a segment number (sequential) component.
Definition: name.hpp:424
size_t size() const noexcept
Returns the number of components.
Definition: name.hpp:155
Name & appendVersion(const optional< uint64_t > &version=nullopt)
Append a version component.
Definition: name.cpp:230
Name & append(const Component &component)
Append a name component.
Definition: name.hpp:283
A prefix announcement object that represents an application's intent of registering a prefix toward i...
const Name & getAnnouncedName() const
Return announced name.
optional< security::ValidityPeriod > getValidityPeriod() const
Return absolute validity period.
PrefixAnnouncement & setValidityPeriod(optional< security::ValidityPeriod > validity)
Set absolute validity period.
time::milliseconds getExpiration() const
Return relative expiration period.
PrefixAnnouncement & setExpiration(time::milliseconds expiration)
Set relative expiration period.
PrefixAnnouncement()
Construct an empty prefix announcement.
PrefixAnnouncement & setAnnouncedName(Name name)
Set announced name.
const Data & toData(KeyChain &keyChain, const ndn::security::SigningInfo &si=security::SigningInfo(), optional< uint64_t > version=nullopt) const
Create a Data packet representing the prefix announcement, if it does not exist.
static const name::Component & getKeywordComponent()
Returns the well-known keyword name component used for prefix announcements (32=PA)
Represents a name component.
Signing parameters passed to KeyChain.
static time_point now() noexcept
Definition: time.cpp:46
#define NDN_THROW(e)
Definition: exception.hpp:61
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
Block makeNonNegativeIntegerBlock(uint32_t type, uint64_t value)
Create a TLV block containing a non-negative integer.
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:31
milliseconds toUnixTimestamp(const system_clock::time_point &point)
Convert system_clock::time_point to UNIX timestamp.
Definition: time.cpp:113
boost::chrono::milliseconds milliseconds
Definition: time.hpp:48
@ ExpirationPeriod
Definition: tlv-nfd.hpp:45
@ Content
Definition: tlv.hpp:93
@ ValidityPeriod
Definition: tlv.hpp:107
@ KeywordNameComponent
Definition: tlv.hpp:75
constexpr bool isCriticalType(uint32_t type) noexcept
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition: tlv.hpp:162
@ ContentType_PrefixAnn
prefix announcement
Definition: tlv.hpp:150
Definition: data.cpp:25
bool operator==(const Data &lhs, const Data &rhs)
Definition: data.cpp:364
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:374