blob: da65e9304dad5a3d26ae515911996bac2b5a568b [file] [log] [blame]
Junxiao Shi8127d1a2018-08-24 15:29:21 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesavento923ba442019-02-12 22:00:38 -05003 * Copyright (c) 2013-2019 Regents of the University of California.
Junxiao Shi8127d1a2018-08-24 15:29:21 -06004 *
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
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/prefix-announcement.hpp"
23#include "ndn-cxx/encoding/tlv-nfd.hpp"
Junxiao Shi8127d1a2018-08-24 15:29:21 -060024
Junxiao Shi8127d1a2018-08-24 15:29:21 -060025namespace ndn {
26
27static const name::Component KEYWORD_PA_COMP = "20025041"_block;
28
29PrefixAnnouncement::PrefixAnnouncement() = default;
30
31PrefixAnnouncement::PrefixAnnouncement(Data data)
32 : m_data(std::move(data))
33{
34 if (m_data->getContentType() != tlv::ContentType_PrefixAnn) {
Davide Pesavento923ba442019-02-12 22:00:38 -050035 NDN_THROW(Error("Data is not a prefix announcement: ContentType is " +
36 to_string(m_data->getContentType())));
Junxiao Shi8127d1a2018-08-24 15:29:21 -060037 }
38
39 const Name& dataName = m_data->getName();
40 if (dataName.size() < 3 || dataName[-3] != KEYWORD_PA_COMP ||
41 !dataName[-2].isVersion() || !dataName[-1].isSegment()) {
Davide Pesavento923ba442019-02-12 22:00:38 -050042 NDN_THROW(Error("Data is not a prefix announcement: wrong name structure"));
Junxiao Shi8127d1a2018-08-24 15:29:21 -060043 }
44 m_announcedName = dataName.getPrefix(-3);
45
46 const Block& payload = m_data->getContent();
47 payload.parse();
48
49 m_expiration = time::milliseconds(readNonNegativeInteger(payload.get(tlv::nfd::ExpirationPeriod)));
50
51 auto validityElement = payload.find(tlv::ValidityPeriod);
52 if (validityElement != payload.elements_end()) {
53 m_validity.emplace(*validityElement);
54 }
55
56 for (const Block& element : payload.elements()) {
57 if (element.type() != tlv::nfd::ExpirationPeriod && element.type() != tlv::ValidityPeriod &&
58 tlv::isCriticalType(element.type())) {
Davide Pesavento923ba442019-02-12 22:00:38 -050059 NDN_THROW(Error("unrecognized element of critical type " + to_string(element.type())));
Junxiao Shi8127d1a2018-08-24 15:29:21 -060060 }
61 }
62}
63
64const Data&
65PrefixAnnouncement::toData(KeyChain& keyChain, const ndn::security::SigningInfo& si,
66 optional<uint64_t> version) const
67{
68 if (!m_data) {
69 Name dataName = m_announcedName;
70 dataName.append(KEYWORD_PA_COMP);
71 dataName.appendVersion(version.value_or(time::toUnixTimestamp(time::system_clock::now()).count()));
72 dataName.appendSegment(0);
73 m_data.emplace(dataName);
Junxiao Shi1748b1e2018-09-06 04:13:42 +000074 m_data->setContentType(tlv::ContentType_PrefixAnn);
Junxiao Shi8127d1a2018-08-24 15:29:21 -060075
76 Block content(tlv::Content);
77 content.push_back(makeNonNegativeIntegerBlock(tlv::nfd::ExpirationPeriod,
78 m_expiration.count()));
79 if (m_validity) {
80 content.push_back(m_validity->wireEncode());
81 }
82 content.encode();
83 m_data->setContent(content);
84
85 keyChain.sign(*m_data, si);
86 }
87 return *m_data;
88}
89
90PrefixAnnouncement&
91PrefixAnnouncement::setAnnouncedName(Name name)
92{
93 m_data.reset();
94 m_announcedName = std::move(name);
95 return *this;
96}
97
98PrefixAnnouncement&
99PrefixAnnouncement::setExpiration(time::milliseconds expiration)
100{
101 if (expiration < 0_ms) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500102 NDN_THROW(std::invalid_argument("expiration period is negative"));
Junxiao Shi8127d1a2018-08-24 15:29:21 -0600103 }
104 m_data.reset();
105 m_expiration = expiration;
106 return *this;
107}
108
109PrefixAnnouncement&
110PrefixAnnouncement::setValidityPeriod(optional<security::ValidityPeriod> validity)
111{
112 m_data.reset();
113 m_validity = std::move(validity);
114 return *this;
115}
116
Junxiao Shi1748b1e2018-09-06 04:13:42 +0000117bool
118operator==(const PrefixAnnouncement& lhs, const PrefixAnnouncement& rhs)
119{
120 return lhs.getAnnouncedName() == rhs.getAnnouncedName() &&
121 lhs.getExpiration() == rhs.getExpiration() &&
122 lhs.getValidityPeriod() == rhs.getValidityPeriod();
123}
124
125std::ostream&
126operator<<(std::ostream& os, const PrefixAnnouncement& pa)
127{
128 os << pa.getAnnouncedName() << " expires=" << pa.getExpiration();
129 if (pa.getValidityPeriod()) {
130 os << " validity=" << *pa.getValidityPeriod();
131 }
132 return os;
133}
134
Junxiao Shi8127d1a2018-08-24 15:29:21 -0600135} // namespace ndn