interest: update ForwardingHint format
Recognize and encode ForwardingHint as a sequence of Names.
The previous format with Delegations is still accepted for decoding, but
Preference field is ignored and no sorting is performed.
Delegation and DelegationList classes have been deleted.
refs #5187
Change-Id: I6f6f94020657b65c3fccb501694416dda24b894b
diff --git a/ndn-cxx/delegation-list.cpp b/ndn-cxx/delegation-list.cpp
deleted file mode 100644
index a051124..0000000
--- a/ndn-cxx/delegation-list.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2019 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#include "ndn-cxx/delegation-list.hpp"
-#include "ndn-cxx/util/ostream-joiner.hpp"
-
-namespace ndn {
-
-BOOST_CONCEPT_ASSERT((boost::EqualityComparable<DelegationList>));
-BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<DelegationList>));
-BOOST_CONCEPT_ASSERT((WireDecodable<DelegationList>));
-
-DelegationList::DelegationList()
- : m_isSorted(true)
-{
-}
-
-DelegationList::DelegationList(std::initializer_list<Delegation> dels)
- : m_isSorted(true)
-{
- for (const Delegation& del : dels) {
- this->insert(del, INS_REPLACE);
- }
-}
-
-DelegationList::DelegationList(const Block& block, bool wantSort)
-{
- this->wireDecode(block, wantSort);
-}
-
-bool
-DelegationList::isValidTlvType(uint32_t type)
-{
- switch (type) {
- case tlv::Content:
- case tlv::ForwardingHint:
- return true;
- default:
- return false;
- }
-}
-
-template<encoding::Tag TAG>
-size_t
-DelegationList::wireEncode(EncodingImpl<TAG>& encoder, uint32_t type) const
-{
- if (!isValidTlvType(type)) {
- NDN_THROW(std::invalid_argument("Unexpected TLV-TYPE " + to_string(type) +
- " while encoding DelegationList"));
- }
-
- if (this->size() == 0) {
- NDN_THROW(Error("Empty DelegationList"));
- }
-
- // LinkContent ::= (type) TLV-LENGTH
- // Delegation+
-
- // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
- // Preference
- // Name
-
- // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
- // nonNegativeInteger
-
- size_t totalLen = 0;
- for (auto i = m_dels.rbegin(); i != m_dels.rend(); ++i) {
- size_t delLen = 0;
- delLen += i->name.wireEncode(encoder);
- delLen += prependNonNegativeIntegerBlock(encoder, tlv::LinkPreference, i->preference);
- delLen += encoder.prependVarNumber(delLen);
- delLen += encoder.prependVarNumber(tlv::LinkDelegation);
- totalLen += delLen;
- }
- totalLen += encoder.prependVarNumber(totalLen);
- totalLen += encoder.prependVarNumber(type);
- return totalLen;
-}
-
-template size_t
-DelegationList::wireEncode<encoding::EncoderTag>(EncodingBuffer&, uint32_t) const;
-
-template size_t
-DelegationList::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, uint32_t) const;
-
-void
-DelegationList::wireDecode(const Block& block, bool wantSort)
-{
- if (!isValidTlvType(block.type())) {
- NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(block.type()) + " while decoding DelegationList"));
- }
-
- m_isSorted = wantSort;
- m_dels.clear();
-
- block.parse();
- for (const auto& del : block.elements()) {
- if (del.type() != tlv::LinkDelegation) {
- NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(del.type()) + " while decoding Delegation"));
- }
- del.parse();
-
- auto val = del.elements_begin();
- if (val == del.elements_end() || val->type() != tlv::LinkPreference) {
- NDN_THROW(Error("Missing Preference field in Delegation"));
- }
- uint64_t preference = 0;
- try {
- preference = readNonNegativeInteger(*val);
- }
- catch (const tlv::Error&) {
- NDN_THROW_NESTED(Error("Invalid Preference field in Delegation"));
- }
-
- ++val;
- if (val == del.elements_end() || val->type() != tlv::Name) {
- NDN_THROW(Error("Missing Name field in Delegation"));
- }
- Name name;
- try {
- name.wireDecode(*val);
- }
- catch (const tlv::Error&) {
- NDN_THROW_NESTED(Error("Invalid Name field in Delegation"));
- }
-
- this->insertImpl(preference, name);
- }
-
- if (this->size() == 0) {
- NDN_THROW(Error("Empty DelegationList"));
- }
-}
-
-void
-DelegationList::sort()
-{
- if (m_isSorted) {
- return;
- }
-
- std::vector<Delegation> dels;
- dels.swap(m_dels);
-
- m_isSorted = true;
- for (const Delegation& del : dels) {
- this->insertImpl(del.preference, del.name);
- }
-}
-
-bool
-DelegationList::insert(uint64_t preference, const Name& name,
- InsertConflictResolution onConflict)
-{
- switch (onConflict) {
- case INS_REPLACE:
- this->eraseImpl(nullopt, name);
- this->insertImpl(preference, name);
- return true;
- case INS_APPEND:
- this->insertImpl(preference, name);
- return true;
- case INS_SKIP:
- if (!std::any_of(m_dels.begin(), m_dels.end(),
- [name] (const Delegation& del) { return del.name == name; })) {
- this->insertImpl(preference, name);
- return true;
- }
- return false;
- }
-
- NDN_THROW(std::invalid_argument("Unknown InsertConflictResolution"));
-}
-
-void
-DelegationList::insertImpl(uint64_t preference, const Name& name)
-{
- if (!m_isSorted) {
- m_dels.push_back({preference, name});
- return;
- }
-
- Delegation del{preference, name};
- auto pos = std::upper_bound(m_dels.begin(), m_dels.end(), del);
- m_dels.insert(pos, del);
-}
-
-size_t
-DelegationList::eraseImpl(optional<uint64_t> preference, const Name& name)
-{
- size_t nErased = 0;
- for (auto i = m_dels.begin(); i != m_dels.end();) {
- if ((!preference || i->preference == *preference) &&
- i->name == name) {
- ++nErased;
- i = m_dels.erase(i);
- }
- else {
- ++i;
- }
- }
- return nErased;
-}
-
-std::ostream&
-operator<<(std::ostream& os, const DelegationList& dl)
-{
- os << '[';
- std::copy(dl.begin(), dl.end(), make_ostream_joiner(os, ','));
- return os << ']';
-}
-
-} // namespace ndn
diff --git a/ndn-cxx/delegation-list.hpp b/ndn-cxx/delegation-list.hpp
deleted file mode 100644
index 9fa7700..0000000
--- a/ndn-cxx/delegation-list.hpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2021 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#ifndef NDN_CXX_DELEGATION_LIST_HPP
-#define NDN_CXX_DELEGATION_LIST_HPP
-
-#include "ndn-cxx/delegation.hpp"
-
-#include <initializer_list>
-
-namespace ndn {
-
-/** \brief represents a list of Delegations
- * \sa https://named-data.net/doc/ndn-tlv/link.html
- *
- * Delegations are stored in an std::vector, under the assumption that there is usually only a
- * small number of Delegations, so that copying is acceptable when they are modified.
- */
-class DelegationList
-{
-public:
- class Error : public tlv::Error
- {
- public:
- using tlv::Error::Error;
- };
-
- /** \brief construct an empty DelegationList
- */
- DelegationList();
-
- /** \brief construct a sorted DelegationList with specified delegations
- *
- * This is equivalent to inserting each delegation into an empty DelegationList with INS_REPLACE
- * conflict resolution.
- */
- DelegationList(std::initializer_list<Delegation> dels);
-
- /** \brief decode a DelegationList
- * \sa wireDecode
- */
- explicit
- DelegationList(const Block& block, bool wantSort = true);
-
- /** \brief encode into wire format
- * \param encoder either an EncodingBuffer or an EncodingEstimator
- * \param type TLV-TYPE number, either Content (for \p Link) or ForwardingHint
- * \throw std::invalid_argument \p type is invalid
- * \throw Error there is no Delegation
- */
- template<encoding::Tag TAG>
- size_t
- wireEncode(EncodingImpl<TAG>& encoder, uint32_t type = tlv::ForwardingHint) const;
-
- /** \brief decode a DelegationList
- * \param block either a Content block (from \p Link) or a ForwardingHint block
- * \param wantSort if true, delegations are sorted
- * \throw Error the block cannot be parsed as a list of Delegations
- */
- void
- wireDecode(const Block& block, bool wantSort = true);
-
- bool
- isSorted() const noexcept
- {
- return m_isSorted;
- }
-
- using const_iterator = std::vector<Delegation>::const_iterator;
-
- const_iterator
- begin() const noexcept
- {
- return m_dels.begin();
- }
-
- const_iterator
- end() const noexcept
- {
- return m_dels.end();
- }
-
- NDN_CXX_NODISCARD bool
- empty() const noexcept
- {
- return m_dels.empty();
- }
-
- size_t
- size() const noexcept
- {
- return m_dels.size();
- }
-
- /** \brief get the i-th delegation
- * \pre i < size()
- */
- const Delegation&
- operator[](size_t i) const
- {
- BOOST_ASSERT(i < size());
- return m_dels[i];
- }
-
- /** \brief get the i-th delegation
- * \throw std::out_of_range i >= size()
- */
- const Delegation&
- at(size_t i) const
- {
- return m_dels.at(i);
- }
-
-public: // modifiers
- /** \brief sort the delegation list
- * \post isSorted() == true
- * \post Delegations are sorted in increasing preference order.
- *
- * A DelegationList can be constructed as sorted or unsorted. In most cases, it is recommended
- * to use a sorted DelegationList. An unsorted DelegationList is useful for extracting the i-th
- * delegation from a received ForwardingHint or Link object.
- *
- * This method turns an unsorted DelegationList into a sorted DelegationList.
- * If access to unsorted DelegationList is not needed, it is more efficient to sort the
- * DelegationList in wireDecode.
- */
- void
- sort();
-
- /** \brief what to do when inserting a duplicate name
- */
- enum InsertConflictResolution {
- /** \brief existing delegation(s) with the same name are replaced with the new delegation
- */
- INS_REPLACE,
-
- /** \brief multiple delegations with the same name are kept in the DelegationList
- * \note This is NOT RECOMMENDED by Link specification.
- */
- INS_APPEND,
-
- /** \brief new delegation is not inserted if an existing delegation has the same name
- */
- INS_SKIP
- };
-
- /** \brief insert Delegation
- * \return whether inserted
- */
- bool
- insert(uint64_t preference, const Name& name,
- InsertConflictResolution onConflict = INS_REPLACE);
-
- /** \brief insert Delegation
- * \return whether inserted
- */
- bool
- insert(const Delegation& del, InsertConflictResolution onConflict = INS_REPLACE)
- {
- return this->insert(del.preference, del.name, onConflict);
- }
-
- /** \brief delete Delegation(s) with specified preference and name
- * \return count of erased Delegation(s)
- */
- size_t
- erase(uint64_t preference, const Name& name)
- {
- return this->eraseImpl(preference, name);
- }
-
- /** \brief delete Delegation(s) with matching preference and name
- * \return count of erased Delegation(s)
- */
- size_t
- erase(const Delegation& del)
- {
- return this->eraseImpl(del.preference, del.name);
- }
-
- /** \brief erase Delegation(s) with specified name
- * \return count of erased Delegation(s)
- */
- size_t
- erase(const Name& name)
- {
- return this->eraseImpl(nullopt, name);
- }
-
-private:
- static bool
- isValidTlvType(uint32_t type);
-
- void
- insertImpl(uint64_t preference, const Name& name);
-
- size_t
- eraseImpl(optional<uint64_t> preference, const Name& name);
-
-private: // non-member operators
- // NOTE: the following "hidden friend" operators are available via
- // argument-dependent lookup only and must be defined inline.
-
- /** \brief Compare whether two DelegationLists are equal.
- * \note Order matters! If two DelegationLists contain the same Delegations but at least one is
- * unsorted, they may compare unequal if the Delegations appear in different order.
- */
- friend bool
- operator==(const DelegationList& lhs, const DelegationList& rhs)
- {
- return lhs.m_dels == rhs.m_dels;
- }
-
- friend bool
- operator!=(const DelegationList& lhs, const DelegationList& rhs)
- {
- return lhs.m_dels != rhs.m_dels;
- }
-
-private:
- bool m_isSorted;
-
- /** \brief delegation container; its contents are sorted when \p m_isSorted is true
- * \note This container is a member field rather than a base class, in order to ensure contents
- * are sorted when \p m_isSorted is true.
- * \note A vector is chosen instead of a std::set, so that the container can be unsorted when
- * \p m_isSorted is false. This container is expected to have less than seven items, and
- * therefore the overhead of moving items during insertion and deletion is small.
- */
- std::vector<Delegation> m_dels;
-};
-
-#ifndef DOXYGEN
-extern template size_t
-DelegationList::wireEncode<encoding::EncoderTag>(EncodingBuffer&, uint32_t) const;
-
-extern template size_t
-DelegationList::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, uint32_t) const;
-#endif
-
-std::ostream&
-operator<<(std::ostream& os, const DelegationList& dl);
-
-} // namespace ndn
-
-#endif // NDN_CXX_DELEGATION_LIST_HPP
diff --git a/ndn-cxx/delegation.hpp b/ndn-cxx/delegation.hpp
deleted file mode 100644
index 6ceb68c..0000000
--- a/ndn-cxx/delegation.hpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2021 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#ifndef NDN_CXX_DELEGATION_HPP
-#define NDN_CXX_DELEGATION_HPP
-
-#include "ndn-cxx/name.hpp"
-
-namespace ndn {
-
-/** \brief Represents a %Delegation.
- * \sa https://named-data.net/doc/NDN-packet-spec/0.3/link.html
- */
-class Delegation
-{
-private: // non-member operators
- // NOTE: the following "hidden friend" operators are available via
- // argument-dependent lookup only and must be defined inline.
-
- friend bool
- operator==(const Delegation& lhs, const Delegation& rhs)
- {
- return !(lhs != rhs);
- }
-
- friend bool
- operator!=(const Delegation& lhs, const Delegation& rhs)
- {
- return lhs.preference != rhs.preference ||
- lhs.name != rhs.name;
- }
-
- friend bool
- operator<(const Delegation& lhs, const Delegation& rhs)
- {
- return std::tie(lhs.preference, lhs.name) <
- std::tie(rhs.preference, rhs.name);
- }
-
- friend bool
- operator<=(const Delegation& lhs, const Delegation& rhs)
- {
- return !(rhs < lhs);
- }
-
- friend bool
- operator>(const Delegation& lhs, const Delegation& rhs)
- {
- return rhs < lhs;
- }
-
- friend bool
- operator>=(const Delegation& lhs, const Delegation& rhs)
- {
- return !(lhs < rhs);
- }
-
- friend std::ostream&
- operator<<(std::ostream& os, const Delegation& d)
- {
- return os << d.name << '(' << d.preference << ')';
- }
-
-public:
- uint64_t preference;
- Name name;
-};
-
-} // namespace ndn
-
-#endif // NDN_CXX_DELEGATION_HPP
diff --git a/ndn-cxx/encoding/block-helpers.hpp b/ndn-cxx/encoding/block-helpers.hpp
index 043ca85..3418d76 100644
--- a/ndn-cxx/encoding/block-helpers.hpp
+++ b/ndn-cxx/encoding/block-helpers.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -299,12 +299,10 @@
{
BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<U>));
- size_t valueLength = value.wireEncode(encoder);
- size_t totalLength = valueLength;
- totalLength += encoder.prependVarNumber(valueLength);
- totalLength += encoder.prependVarNumber(type);
-
- return totalLength;
+ size_t length = value.wireEncode(encoder);
+ length += encoder.prependVarNumber(length);
+ length += encoder.prependVarNumber(type);
+ return length;
}
/** @brief Create a TLV block containing a nested TLV element.
@@ -322,7 +320,52 @@
EncodingBuffer encoder(totalLength, 0);
prependNestedBlock(encoder, type, value);
+ return encoder.block();
+}
+/** @brief Prepend a TLV element containing a sequence of nested TLV elements.
+ * @tparam I bidirectional iterator to a type that satisfies WireEncodableWithEncodingBuffer concept
+ * @param encoder an EncodingBuffer or EncodingEstimator
+ * @param type TLV-TYPE number for outer TLV element
+ * @param first begin iterator to inner TLV elements
+ * @param last past-end iterator to inner TLV elements
+ * @sa makeNestedBlock
+ */
+template<Tag TAG, class I>
+size_t
+prependNestedBlock(EncodingImpl<TAG>& encoder, uint32_t type, I first, I last)
+{
+ BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<typename std::iterator_traits<I>::value_type>));
+
+ auto rfirst = std::make_reverse_iterator(last);
+ auto rlast = std::make_reverse_iterator(first);
+
+ size_t length = 0;
+ for (auto i = rfirst; i != rlast; ++i) {
+ length += i->wireEncode(encoder);
+ }
+
+ length += encoder.prependVarNumber(length);
+ length += encoder.prependVarNumber(type);
+ return length;
+}
+
+/** @brief Create a TLV block containing a sequence of nested TLV elements.
+ * @tparam I bidirectional iterator to a type that satisfies WireEncodableWithEncodingBuffer concept
+ * @param type TLV-TYPE number for outer TLV element
+ * @param first begin iterator to inner TLV elements
+ * @param last past-end iterator to inner TLV elements
+ * @sa prependNestedBlock
+ */
+template<class I>
+Block
+makeNestedBlock(uint32_t type, I first, I last)
+{
+ EncodingEstimator estimator;
+ size_t totalLength = prependNestedBlock(estimator, type, first, last);
+
+ EncodingBuffer encoder(totalLength, 0);
+ prependNestedBlock(encoder, type, first, last);
return encoder.block();
}
diff --git a/ndn-cxx/interest.cpp b/ndn-cxx/interest.cpp
index f1b3171..ea0302c 100644
--- a/ndn-cxx/interest.cpp
+++ b/ndn-cxx/interest.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -110,8 +110,9 @@
totalLength += encoder.prependByteArrayBlock(tlv::Nonce, m_nonce->data(), m_nonce->size());
// ForwardingHint
- if (!getForwardingHint().empty()) {
- totalLength += getForwardingHint().wireEncode(encoder);
+ if (!m_forwardingHint.empty()) {
+ totalLength += prependNestedBlock(encoder, tlv::ForwardingHint,
+ m_forwardingHint.begin(), m_forwardingHint.end());
}
// MustBeFresh
@@ -186,7 +187,7 @@
m_name = std::move(tempName);
m_canBePrefix = m_mustBeFresh = false;
- m_forwardingHint = {};
+ m_forwardingHint.clear();
m_nonce.reset();
m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
m_hopLimit.reset();
@@ -221,7 +222,37 @@
if (lastElement >= 4) {
NDN_THROW(Error("ForwardingHint element is out of order"));
}
- m_forwardingHint.wireDecode(*element);
+ // ForwardingHint = FORWARDING-HINT-TYPE TLV-LENGTH 1*Name
+ // [previous format]
+ // ForwardingHint = FORWARDING-HINT-TYPE TLV-LENGTH 1*Delegation
+ // Delegation = DELEGATION-TYPE TLV-LENGTH Preference Name
+ element->parse();
+ for (const auto& del : element->elements()) {
+ switch (del.type()) {
+ case tlv::Name:
+ try {
+ m_forwardingHint.emplace_back(del);
+ }
+ catch (const tlv::Error&) {
+ NDN_THROW_NESTED(Error("Invalid Name in ForwardingHint"));
+ }
+ break;
+ case tlv::LinkDelegation:
+ try {
+ del.parse();
+ m_forwardingHint.emplace_back(del.get(tlv::Name));
+ }
+ catch (const tlv::Error&) {
+ NDN_THROW_NESTED(Error("Invalid Name in ForwardingHint.Delegation"));
+ }
+ break;
+ default:
+ if (tlv::isCriticalType(del.type())) {
+ NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(del.type()) + " while decoding ForwardingHint"));
+ }
+ break;
+ }
+ }
lastElement = 4;
break;
}
@@ -356,9 +387,9 @@
}
Interest&
-Interest::setForwardingHint(const DelegationList& value)
+Interest::setForwardingHint(std::vector<Name> value)
{
- m_forwardingHint = value;
+ m_forwardingHint = std::move(value);
m_wire.reset();
return *this;
}
diff --git a/ndn-cxx/interest.hpp b/ndn-cxx/interest.hpp
index 39004c5..4abfe0c 100644
--- a/ndn-cxx/interest.hpp
+++ b/ndn-cxx/interest.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -22,7 +22,6 @@
#ifndef NDN_CXX_INTEREST_HPP
#define NDN_CXX_INTEREST_HPP
-#include "ndn-cxx/delegation-list.hpp"
#include "ndn-cxx/detail/packet-base.hpp"
#include "ndn-cxx/name.hpp"
#include "ndn-cxx/security/security-common.hpp"
@@ -240,33 +239,14 @@
return *this;
}
- const DelegationList&
+ span<const Name>
getForwardingHint() const noexcept
{
return m_forwardingHint;
}
Interest&
- setForwardingHint(const DelegationList& value);
-
- /** @brief Modify ForwardingHint in-place.
- * @tparam Modifier a unary function that accepts DelegationList&
- *
- * This is equivalent to, but more efficient (avoids copying) than:
- * @code
- * auto fh = interest.getForwardingHint();
- * modifier(fh);
- * interest.setForwardingHint(fh);
- * @endcode
- */
- template<typename Modifier>
- Interest&
- modifyForwardingHint(const Modifier& modifier)
- {
- modifier(m_forwardingHint);
- m_wire.reset();
- return *this;
- }
+ setForwardingHint(std::vector<Name> value);
/** @brief Check if the Nonce element is present.
*/
@@ -499,7 +479,7 @@
static bool s_autoCheckParametersDigest;
Name m_name;
- DelegationList m_forwardingHint;
+ std::vector<Name> m_forwardingHint;
mutable optional<Nonce> m_nonce;
time::milliseconds m_interestLifetime;
optional<uint8_t> m_hopLimit;
diff --git a/ndn-cxx/link.cpp b/ndn-cxx/link.cpp
index ab5cb0d..54e9321 100644
--- a/ndn-cxx/link.cpp
+++ b/ndn-cxx/link.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -32,14 +32,14 @@
Link::Link() = default;
-Link::Link(const Block& wire, bool wantSort)
+Link::Link(const Block& wire)
{
- this->wireDecode(wire, wantSort);
+ this->wireDecode(wire);
}
-Link::Link(const Name& name, std::initializer_list<Delegation> dels)
+Link::Link(const Name& name, std::initializer_list<Name> delegations)
: Data(name)
- , m_delList(dels)
+ , m_delegations(delegations)
{
encodeContent();
}
@@ -49,22 +49,16 @@
{
setContentType(tlv::ContentType_Link);
- if (m_delList.size() > 0) {
- EncodingEstimator estimator;
- size_t estimatedSize = m_delList.wireEncode(estimator, tlv::Content);
-
- EncodingBuffer buffer(estimatedSize, 0);
- m_delList.wireEncode(buffer, tlv::Content);
-
- setContent(buffer.block());
- }
- else {
+ if (m_delegations.empty()) {
setContent(nullptr, 0);
+ return;
}
+
+ setContent(makeNestedBlock(tlv::Content, m_delegations.begin(), m_delegations.end()));
}
void
-Link::wireDecode(const Block& wire, bool wantSort)
+Link::wireDecode(const Block& wire)
{
Data::wireDecode(wire);
@@ -72,31 +66,51 @@
NDN_THROW(Error("Expecting ContentType Link, got " + to_string(getContentType())));
}
- m_delList.wireDecode(getContent(), wantSort);
+ // LinkContent = CONTENT-TYPE TLV-LENGTH 1*Name
+
+ m_delegations.clear();
+ auto content = getContent();
+ content.parse();
+ for (const auto& del : content.elements()) {
+ if (del.type() == tlv::Name) {
+ m_delegations.emplace_back(del);
+ }
+ else if (tlv::isCriticalType(del.type())) {
+ NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(del.type()) + " while decoding LinkContent"));
+ }
+ }
}
void
-Link::setDelegationList(const DelegationList& dels)
+Link::setDelegationList(std::vector<Name> delegations)
{
- m_delList = dels;
+ m_delegations = std::move(delegations);
encodeContent();
}
-void
-Link::addDelegation(uint32_t preference, const Name& name)
+bool
+Link::addDelegation(const Name& name)
{
- m_delList.insert(preference, name, DelegationList::INS_REPLACE);
+ if (std::find(m_delegations.begin(), m_delegations.end(), name) != m_delegations.end()) {
+ return false;
+ }
+
+ m_delegations.push_back(name);
encodeContent();
+ return true;
}
bool
Link::removeDelegation(const Name& name)
{
- size_t nErased = m_delList.erase(name);
- if (nErased > 0) {
- encodeContent();
+ auto last = std::remove(m_delegations.begin(), m_delegations.end(), name);
+ if (last == m_delegations.end()) {
+ return false;
}
- return nErased > 0;
+
+ m_delegations.erase(last, m_delegations.end());
+ encodeContent();
+ return true;
}
} // namespace ndn
diff --git a/ndn-cxx/link.hpp b/ndn-cxx/link.hpp
index 53f6258..b245530 100644
--- a/ndn-cxx/link.hpp
+++ b/ndn-cxx/link.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -23,7 +23,6 @@
#define NDN_CXX_LINK_HPP
#include "ndn-cxx/data.hpp"
-#include "ndn-cxx/delegation-list.hpp"
namespace ndn {
@@ -49,7 +48,6 @@
/** @brief Decode a Link object from a Block
* @param wire a TLV block
- * @param wantSort if false, relative order among delegations is preserved
*
* Note that in certain contexts that use Link::shared_from_this(), Link must be
* created using `make_shared`:
@@ -57,51 +55,49 @@
* shared_ptr<Link> linkObject = make_shared<Link>(block);
*/
explicit
- Link(const Block& wire, bool wantSort = true);
+ Link(const Block& wire);
/** @brief Create a Link object with the given name and delegations
* @param name A reference to the name of the redirected namespace
- * @param dels Delegations in payload
+ * @param delegations Delegations in payload
*
* Note that in certain contexts that use Link::shared_from_this(), Link must be
* created using `make_shared`:
*
- * shared_ptr<Link> link = make_shared<Link>(name, dels);
+ * shared_ptr<Link> link = make_shared<Link>(name, delegations);
*/
explicit
- Link(const Name& name, std::initializer_list<Delegation> dels = {});
+ Link(const Name& name, std::initializer_list<Name> delegations = {});
/** @brief Decode from the wire format
* @param wire a TLV block
- * @param wantSort if false, relative order among delegations is preserved
*/
void
- wireDecode(const Block& wire, bool wantSort = true);
+ wireDecode(const Block& wire);
/** @brief Get the delegations
*/
- const DelegationList&
+ span<const Name>
getDelegationList() const
{
- return m_delList;
+ return m_delegations;
}
/** @brief Set the delegations
* @note This is more efficient than multiple addDelegation and removeDelegation invocations.
*/
void
- setDelegationList(const DelegationList& dels);
+ setDelegationList(std::vector<Name> delegations);
- /** @brief Add a delegation in the format of <Name, Preference>
- * @param preference The preference of the delegation to be added
- * @param name The name of the delegation to be added
- * @note If a delegation with @p name exists, its preference will be updated
+ /** @brief Append a delegation at the end
+ * @param name Delegation name
+ * @return true if delegation is added, false if same name already exists
*/
- void
- addDelegation(uint32_t preference, const Name& name);
+ bool
+ addDelegation(const Name& name);
/** @brief Remove a delegation whose name is @p name
- * @param name The name of the delegation to be removed
+ * @param name Delegation name
* @return true if delegation is removed, otherwise false
*/
bool
@@ -112,7 +108,7 @@
encodeContent();
private:
- DelegationList m_delList;
+ std::vector<Name> m_delegations;
};
} // namespace ndn
diff --git a/tests/unit/delegation-list.t.cpp b/tests/unit/delegation-list.t.cpp
deleted file mode 100644
index 0831dca..0000000
--- a/tests/unit/delegation-list.t.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#include "ndn-cxx/delegation-list.hpp"
-
-#include "tests/boost-test.hpp"
-#include <boost/lexical_cast.hpp>
-
-namespace ndn {
-namespace tests {
-
-BOOST_AUTO_TEST_SUITE(TestDelegationList)
-
-const uint8_t DEL1A[] = {
- 0x1f, 0x08, // Delegation
- 0x1e, 0x01, 0x01, // Preference=1
- 0x07, 0x03, 0x08, 0x01, 0x41 // Name=/A
-};
-const uint8_t DEL1B[] = {
- 0x1f, 0x08, // Delegation
- 0x1e, 0x01, 0x01, // Preference=1
- 0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
-};
-const uint8_t DEL2A[] = {
- 0x1f, 0x08, // Delegation
- 0x1e, 0x01, 0x02, // Preference=2
- 0x07, 0x03, 0x08, 0x01, 0x41 // Name=/A
-};
-const uint8_t DEL2B[] = {
- 0x1f, 0x08, // Delegation
- 0x1e, 0x01, 0x02, // Preference=2
- 0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
-};
-
-Block
-makeDelegationListBlock(uint32_t type, std::initializer_list<const uint8_t*> dels)
-{
- Block block(type);
- for (const uint8_t* del : dels) {
- block.push_back(Block(del, 2 + del[1]));
- }
- block.encode();
- return block;
-}
-
-BOOST_AUTO_TEST_SUITE(Decode)
-
-BOOST_AUTO_TEST_CASE(DecodeUnsorted)
-{
- DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL2B, DEL1A}), false);
- BOOST_CHECK_EQUAL(dl.size(), 3);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
- BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(1).name, "/B");
- BOOST_CHECK_EQUAL(dl.at(2).preference, 1);
- BOOST_CHECK_EQUAL(dl.at(2).name, "/A");
-}
-
-BOOST_AUTO_TEST_CASE(DecodeSorted)
-{
- DelegationList dl(makeDelegationListBlock(tlv::Content, {DEL2A, DEL2B, DEL1A}));
- BOOST_CHECK_EQUAL(dl.size(), 3);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
- BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
- BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(1).name, "/A");
- BOOST_CHECK_EQUAL(dl.at(2).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(2).name, "/B");
-}
-
-BOOST_AUTO_TEST_CASE(DecodeEmpty)
-{
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::ForwardingHint, {});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeBadType)
-{
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::Selectors, {DEL1A, DEL2B});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeNotDelegation)
-{
- const uint8_t BAD_DEL[] = {
- 0x09, 0x00 // Selectors
- };
-
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeMissingPreference)
-{
- const uint8_t BAD_DEL[] = {
- 0x1f, 0x05, // Delegation
- 0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
- };
-
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeMissingName)
-{
- const uint8_t BAD_DEL[] = {
- 0x1f, 0x03, // Delegation
- 0x1e, 0x01, 0x02, // Preference=2
- };
-
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeUnknownField)
-{
- const uint8_t BAD_DEL[] = {
- 0x1f, 0x0a, // Delegation
- 0x1e, 0x01, 0x02, // Preference=2
- 0x09, 0x00, // Selectors
- 0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
- };
-
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeWrongOrder)
-{
- const uint8_t BAD_DEL[] = {
- 0x1f, 0x08, // Delegation
- 0x07, 0x03, 0x08, 0x01, 0x42, // Name=/B
- 0x1e, 0x01, 0x02 // Preference=2
- };
-
- DelegationList dl;
- Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
- BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Decode
-
-BOOST_AUTO_TEST_SUITE(InsertEncode)
-
-BOOST_AUTO_TEST_CASE(InsertSimple)
-{
- DelegationList dl;
- BOOST_CHECK_EQUAL(dl.empty(), true);
- dl.insert(2, "/A");
- BOOST_CHECK_EQUAL(dl.empty(), false);
- dl.insert(1, "/B");
- BOOST_CHECK_EQUAL(dl.size(), 2);
-
- EncodingBuffer encoder;
- dl.wireEncode(encoder);
- BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL1B, DEL2A}));
-}
-
-BOOST_AUTO_TEST_CASE(InsertReplace)
-{
- DelegationList dl({{2, "/A"}});
- dl.insert(Delegation{1, "/A"}, DelegationList::INS_REPLACE);
- BOOST_CHECK_EQUAL(dl.size(), 1);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
- BOOST_CHECK_EQUAL(dl[0].name, "/A");
-
- EncodingBuffer encoder;
- dl.wireEncode(encoder);
- BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL1A}));
-}
-
-BOOST_AUTO_TEST_CASE(InsertAppend)
-{
- DelegationList dl({{2, "/A"}});
- dl.insert(Delegation{1, "/A"}, DelegationList::INS_APPEND);
- BOOST_CHECK_EQUAL(dl.size(), 2);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
- BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
-
- EncodingBuffer encoder;
- dl.wireEncode(encoder);
- BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, DEL2A}));
-}
-
-BOOST_AUTO_TEST_CASE(InsertSkip)
-{
- DelegationList dl({{2, "/A"}});
- dl.insert(Delegation{1, "/A"}, DelegationList::INS_SKIP);
- BOOST_CHECK_EQUAL(dl.size(), 1);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 2);
-
- EncodingBuffer encoder;
- dl.wireEncode(encoder);
- BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL2A}));
-}
-
-BOOST_AUTO_TEST_CASE(Unsorted)
-{
- DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A}), false);
- dl.insert(1, "/B");
- BOOST_CHECK_EQUAL(dl.size(), 2);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
- BOOST_CHECK_EQUAL(dl.at(1).preference, 1);
- BOOST_CHECK_EQUAL(dl.at(1).name, "/B");
-
- EncodingBuffer encoder;
- dl.wireEncode(encoder, tlv::Content);
- BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::Content, {DEL2A, DEL1B}));
-}
-
-BOOST_AUTO_TEST_CASE(EncodeBadType)
-{
- DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A}));
- EncodingBuffer encoder;
- BOOST_CHECK_THROW(dl.wireEncode(encoder, tlv::Selectors), std::invalid_argument);
-}
-
-BOOST_AUTO_TEST_CASE(EncodeEmpty)
-{
- DelegationList dl;
- EncodingBuffer encoder;
- BOOST_CHECK_THROW(dl.wireEncode(encoder), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // InsertEncode
-
-BOOST_AUTO_TEST_SUITE(Erase)
-
-BOOST_AUTO_TEST_CASE(EraseNoop)
-{
- DelegationList dl;
- dl.insert(1, "/A");
- BOOST_CHECK_EQUAL(dl.erase(2, "/A"), 0);
- BOOST_CHECK_EQUAL(dl.erase(Delegation{1, "/B"}), 0);
- BOOST_CHECK_EQUAL(dl.size(), 1);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
- BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
-}
-
-BOOST_AUTO_TEST_CASE(EraseOne)
-{
- DelegationList dl;
- dl.insert(1, "/A");
- BOOST_CHECK_EQUAL(dl.erase(1, "/A"), 1);
- BOOST_CHECK_EQUAL(dl.size(), 0);
-}
-
-BOOST_AUTO_TEST_CASE(EraseByName)
-{
- DelegationList dl;
- dl.insert(1, "/A");
- dl.insert(2, "/A", DelegationList::INS_APPEND);
- BOOST_CHECK_EQUAL(dl.size(), 2);
- BOOST_CHECK_EQUAL(dl.erase("/A"), 2);
- BOOST_CHECK_EQUAL(dl.size(), 0);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Erase
-
-BOOST_AUTO_TEST_SUITE(Sort)
-
-BOOST_AUTO_TEST_CASE(Noop)
-{
- DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL1A}));
- BOOST_CHECK_EQUAL(dl.isSorted(), true);
- dl.sort();
- BOOST_CHECK_EQUAL(dl.isSorted(), true);
-}
-
-BOOST_AUTO_TEST_CASE(Sort)
-{
- DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL2B, DEL1A}), false);
- BOOST_CHECK_EQUAL(dl.isSorted(), false);
- dl.sort();
- BOOST_CHECK_EQUAL(dl.isSorted(), true);
- BOOST_CHECK_EQUAL(dl.size(), 3);
- BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
- BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
- BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(1).name, "/A");
- BOOST_CHECK_EQUAL(dl.at(2).preference, 2);
- BOOST_CHECK_EQUAL(dl.at(2).name, "/B");
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Sort
-
-BOOST_AUTO_TEST_SUITE(Compare)
-
-BOOST_AUTO_TEST_CASE(Empty)
-{
- DelegationList dl1, dl2;
- BOOST_CHECK_EQUAL(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(SortedEqual)
-{
- DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B})),
- dl2(makeDelegationListBlock(tlv::Content, {DEL1B, DEL2A}));
- BOOST_CHECK_EQUAL(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(SortedUnequal)
-{
- DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B})),
- dl2(makeDelegationListBlock(tlv::Content, {DEL1A, DEL2B}));
- BOOST_CHECK_NE(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(UnsortedSameOrder)
-{
- DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B}), false),
- dl2(makeDelegationListBlock(tlv::Content, {DEL2A, DEL1B}), false);
- BOOST_CHECK_EQUAL(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(UnsortedDifferentOrder)
-{
- DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B}), false),
- dl2(makeDelegationListBlock(tlv::Content, {DEL1B, DEL2A}), false);
- BOOST_CHECK_NE(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Compare
-
-BOOST_AUTO_TEST_SUITE(Print)
-
-BOOST_AUTO_TEST_CASE(PrintEmpty)
-{
- DelegationList dl;
- BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(dl), "[]");
-}
-
-BOOST_AUTO_TEST_CASE(PrintNormal)
-{
- DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B}));
- BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(dl), "[/B(1),/A(2)]");
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Print
-
-BOOST_AUTO_TEST_SUITE_END() // TestDelegationList
-
-} // namespace tests
-} // namespace ndn
diff --git a/tests/unit/delegation.t.cpp b/tests/unit/delegation.t.cpp
deleted file mode 100644
index 9f23e89..0000000
--- a/tests/unit/delegation.t.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#include "ndn-cxx/delegation.hpp"
-
-#include "tests/boost-test.hpp"
-#include <boost/lexical_cast.hpp>
-
-namespace ndn {
-namespace tests {
-
-BOOST_AUTO_TEST_SUITE(TestDelegation)
-
-BOOST_AUTO_TEST_CASE(Compare)
-{
- BOOST_CHECK_EQUAL((Delegation{1, "/A"}), (Delegation{1, "/A"}));
- BOOST_CHECK_LE((Delegation{1, "/A"}), (Delegation{1, "/A"}));
- BOOST_CHECK_GE((Delegation{1, "/A"}), (Delegation{1, "/A"}));
-
- BOOST_CHECK_NE((Delegation{1, "/A"}), (Delegation{2, "/A"}));
- BOOST_CHECK_NE((Delegation{1, "/A"}), (Delegation{1, "/B"}));
-
- BOOST_CHECK_LT((Delegation{1, "/A"}), (Delegation{1, "/B"}));
- BOOST_CHECK_LE((Delegation{1, "/A"}), (Delegation{1, "/B"}));
- BOOST_CHECK_LT((Delegation{1, "/B"}), (Delegation{2, "/A"}));
- BOOST_CHECK_LE((Delegation{1, "/B"}), (Delegation{2, "/A"}));
- BOOST_CHECK_LT((Delegation{1, "/A"}), (Delegation{2, "/A"}));
- BOOST_CHECK_LE((Delegation{1, "/A"}), (Delegation{2, "/A"}));
-
- BOOST_CHECK_GT((Delegation{1, "/B"}), (Delegation{1, "/A"}));
- BOOST_CHECK_GE((Delegation{1, "/B"}), (Delegation{1, "/A"}));
- BOOST_CHECK_GT((Delegation{2, "/A"}), (Delegation{1, "/B"}));
- BOOST_CHECK_GE((Delegation{2, "/A"}), (Delegation{1, "/B"}));
- BOOST_CHECK_GT((Delegation{2, "/A"}), (Delegation{1, "/A"}));
- BOOST_CHECK_GE((Delegation{2, "/A"}), (Delegation{1, "/A"}));
-}
-
-BOOST_AUTO_TEST_CASE(Print)
-{
- BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(Delegation{1, "/B"}), "/B(1)");
-}
-
-BOOST_AUTO_TEST_SUITE_END() // TestDelegation
-
-} // namespace tests
-} // namespace ndn
diff --git a/tests/unit/encoding/block-helpers.t.cpp b/tests/unit/encoding/block-helpers.t.cpp
index 4b26109..2ca1e02 100644
--- a/tests/unit/encoding/block-helpers.t.cpp
+++ b/tests/unit/encoding/block-helpers.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -134,6 +134,21 @@
BOOST_CHECK_EQUAL(*b1.elements().begin(), name.wireEncode());
}
+BOOST_AUTO_TEST_CASE(NestedSequence)
+{
+ std::vector<Name> names;
+ names.emplace_back("/A");
+ names.emplace_back("/B");
+ Block b1 = makeNestedBlock(100, names.begin(), names.end());
+
+ BOOST_CHECK_EQUAL(b1.type(), 100);
+ b1.parse();
+ auto elements = b1.elements();
+ BOOST_REQUIRE_EQUAL(elements.size(), 2);
+ BOOST_CHECK_EQUAL(Name(elements[0]), names[0]);
+ BOOST_CHECK_EQUAL(Name(elements[1]), names[1]);
+}
+
BOOST_AUTO_TEST_SUITE_END() // TestBlockHelpers
BOOST_AUTO_TEST_SUITE_END() // Encoding
diff --git a/tests/unit/interest.t.cpp b/tests/unit/interest.t.cpp
index b630e64..482eac8 100644
--- a/tests/unit/interest.t.cpp
+++ b/tests/unit/interest.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -153,7 +153,7 @@
BOOST_AUTO_TEST_CASE(Full)
{
const uint8_t WIRE[] = {
- 0x05, 0x5c, // Interest
+ 0x05, 0x56, // Interest
0x07, 0x36, // Name
0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // GenericNameComponent
0x08, 0x03, 0x6e, 0x64, 0x6e, // GenericNameComponent
@@ -164,12 +164,8 @@
0xcc, 0xd7, 0x2c, 0x6e, 0xa0, 0xf7, 0x31, 0x5a,
0x21, 0x00, // CanBePrefix
0x12, 0x00, // MustBeFresh
- 0x1e, 0x0b, // ForwardingHint
- 0x1f, 0x09, // Delegation List
- 0x1e, 0x02,
- 0x3e, 0x15,
- 0x07, 0x03,
- 0x08, 0x01, 0x48,
+ 0x1e, 0x05, // ForwardingHint
+ 0x07, 0x03, 0x08, 0x01, 0x48,
0x0a, 0x04, // Nonce
0x4c, 0x1e, 0xcb, 0x4a,
0x0c, 0x02, // InterestLifetime
@@ -184,7 +180,7 @@
i1.setName("/local/ndn/prefix");
i1.setMustBeFresh(true);
i1.setCanBePrefix(true);
- i1.setForwardingHint(DelegationList({{15893, "/H"}}));
+ i1.setForwardingHint({"/H"});
i1.setNonce(0x4c1ecb4a);
i1.setInterestLifetime(30369_ms);
i1.setHopLimit(220);
@@ -199,7 +195,7 @@
"/local/ndn/prefix/params-sha256=ff9100e04eaadcf30674d98026a051ba25f56b69bfa026dcccd72c6ea0f7315a");
BOOST_CHECK_EQUAL(i2.getCanBePrefix(), true);
BOOST_CHECK_EQUAL(i2.getMustBeFresh(), true);
- BOOST_CHECK_EQUAL(i2.getForwardingHint(), DelegationList({{15893, "/H"}}));
+ BOOST_TEST(i2.getForwardingHint() == std::vector<Name>({"/H"}), boost::test_tools::per_element());
BOOST_CHECK_EQUAL(i2.hasNonce(), true);
BOOST_CHECK_EQUAL(i2.getNonce(), 0x4c1ecb4a);
BOOST_CHECK_EQUAL(i2.getInterestLifetime(), 30369_ms);
@@ -385,7 +381,7 @@
{
// initialize all elements to non-empty, to verify wireDecode clears them
i.setName("/A");
- i.setForwardingHint({{10309, "/F"}});
+ i.setForwardingHint({"/F"});
i.setNonce(0x03d645a8);
i.setInterestLifetime(18554_ms);
i.setHopLimit(64);
@@ -448,7 +444,7 @@
BOOST_CHECK_EQUAL(i.getName(), "/I");
BOOST_CHECK_EQUAL(i.getCanBePrefix(), true);
BOOST_CHECK_EQUAL(i.getMustBeFresh(), true);
- BOOST_CHECK_EQUAL(i.getForwardingHint(), DelegationList({{15893, "/H"}}));
+ BOOST_TEST(i.getForwardingHint() == std::vector<Name>({"/H"}), boost::test_tools::per_element());
BOOST_CHECK_EQUAL(i.hasNonce(), true);
BOOST_CHECK_EQUAL(i.getNonce(), 0x4acb1e4c);
BOOST_CHECK_EQUAL(i.getInterestLifetime(), 30369_ms);
@@ -459,11 +455,13 @@
// encode without modification: retain original wire encoding
BOOST_CHECK_EQUAL(i.wireEncode().value_size(), 49);
- // modify then re-encode: unrecognized elements are discarded
+ // modify then re-encode:
+ // * unrecognized elements are discarded;
+ // * ForwardingHint is re-encoded as a sequence of Names
i.setName("/J");
BOOST_CHECK_EQUAL(i.wireEncode(),
- "0523 0703(08014A) "
- "2100 1200 1E0B(1F09 1E023E15 0703080148) "
+ "051D 0703(08014A) "
+ "2100 1200 1E05(0703080148) "
"0A044ACB1E4C 0C0276A1 2201D6"_block);
}
@@ -476,7 +474,7 @@
"/I/params-sha256=f16db273f40436a852063f864d5072b01ead53151f5a688ea1560492bebedd05");
BOOST_CHECK_EQUAL(i.getCanBePrefix(), true);
BOOST_CHECK_EQUAL(i.getMustBeFresh(), true);
- BOOST_CHECK_EQUAL(i.getForwardingHint(), DelegationList({{15893, "/H"}}));
+ BOOST_TEST(i.getForwardingHint() == std::vector<Name>({"/H"}), boost::test_tools::per_element());
BOOST_CHECK_EQUAL(i.hasNonce(), true);
BOOST_CHECK_EQUAL(i.getNonce(), 0x4acb1e4c);
BOOST_CHECK_EQUAL(i.getInterestLifetime(), 30369_ms);
@@ -487,21 +485,22 @@
// encode without modification: retain original wire encoding
BOOST_CHECK_EQUAL(i.wireEncode().value_size(), 91);
- // modify then re-encode: unrecognized elements after ApplicationParameters
- // are preserved, the rest are discarded
+ // modify then re-encode:
+ // * unrecognized elements after ApplicationParameters are preserved, the rest are discarded;
+ // * ForwardingHint is re-encoded as a sequence of Names
i.setName("/J");
BOOST_CHECK_EQUAL(i.isParametersDigestValid(), true);
BOOST_CHECK_EQUAL(i.wireEncode(),
- "054D 0725(08014A 0220F16DB273F40436A852063F864D5072B01EAD53151F5A688EA1560492BEBEDD05) "
- "2100 1200 1E0B(1F09 1E023E15 0703080148) "
+ "0547 0725(08014A 0220F16DB273F40436A852063F864D5072B01EAD53151F5A688EA1560492BEBEDD05) "
+ "2100 1200 1E05(0703080148) "
"0A044ACB1E4C 0C0276A1 2201D6 2404C0C1C2C3 FC00"_block);
// modify ApplicationParameters: unrecognized elements are preserved
i.setApplicationParameters("2402CAFE"_block);
BOOST_CHECK_EQUAL(i.isParametersDigestValid(), true);
BOOST_CHECK_EQUAL(i.wireEncode(),
- "054B 0725(08014A 02205FDA67967EE302FC457E41B7D3D51BA6A9379574D193FD88F64954BF16C2927A) "
- "2100 1200 1E0B(1F09 1E023E15 0703080148) "
+ "0545 0725(08014A 02205FDA67967EE302FC457E41B7D3D51BA6A9379574D193FD88F64954BF16C2927A) "
+ "2100 1200 1E05(0703080148) "
"0A044ACB1E4C 0C0276A1 2201D6 2402CAFE FC00"_block);
}
@@ -689,7 +688,7 @@
interest.setName("/A")
.setCanBePrefix(true)
.setMustBeFresh(true)
- .setForwardingHint({{1, "/H"}})
+ .setForwardingHint({"/H"})
.setNonce(2228)
.setInterestLifetime(5_s)
.setHopLimit(90);
@@ -706,7 +705,8 @@
other.setMustBeFresh(interest.getMustBeFresh());
BOOST_CHECK_EQUAL(interest.matchesInterest(other), false); // will match until #3162 implemented
- other.setForwardingHint(interest.getForwardingHint());
+ auto fh = interest.getForwardingHint();
+ other.setForwardingHint(std::vector<Name>(fh.begin(), fh.end()));
BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
other.setNonce(9336);
@@ -754,19 +754,6 @@
BOOST_CHECK_EQUAL(i.getMustBeFresh(), false);
}
-BOOST_AUTO_TEST_CASE(ModifyForwardingHint)
-{
- Interest i("/I");
- i.setCanBePrefix(false);
- i.setForwardingHint({{1, "/A"}});
- i.wireEncode();
- BOOST_CHECK(i.hasWire());
-
- i.modifyForwardingHint([] (DelegationList& fh) { fh.insert(2, "/B"); });
- BOOST_CHECK(!i.hasWire());
- BOOST_CHECK_EQUAL(i.getForwardingHint(), DelegationList({{1, "/A"}, {2, "/B"}}));
-}
-
BOOST_AUTO_TEST_CASE(GetNonce)
{
unique_ptr<Interest> i1, i2;
diff --git a/tests/unit/link.t.cpp b/tests/unit/link.t.cpp
index 1042d35..2d7fa9c 100644
--- a/tests/unit/link.t.cpp
+++ b/tests/unit/link.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -29,7 +29,7 @@
BOOST_AUTO_TEST_SUITE(TestLink)
const uint8_t GOOD_LINK[] = {
-0x06, 0xda, // Data
+0x06, 0xd0, // Data
0x07, 0x14, // Name
0x08, 0x05,
0x6c, 0x6f, 0x63, 0x61, 0x6c,
@@ -42,19 +42,13 @@
0x01,
0x19, 0x02, // FreshnessPeriod
0x27, 0x10,
- 0x15, 0x1a, // Content
- 0x1f, 0x0c, // LinkDelegation
- 0x1e, 0x01, // LinkPreference
- 0x0a,
- 0x07, 0x07, // Name
- 0x08, 0x05,
- 0x6c, 0x6f, 0x63, 0x61, 0x6c,
- 0x1f, 0x0a, // LinkDelegation
- 0x1e, 0x01, // LinkPreference
- 0x14,
- 0x07, 0x05, // Name
- 0x08, 0x03,
- 0x6e, 0x64, 0x6e,
+ 0x15, 0x10, // Content
+ 0x07, 0x07, // Name
+ 0x08, 0x05,
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x07, 0x05, // Name
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
0x16, 0x1b, // SignatureInfo
0x1b, 0x01, // SignatureType
0x01,
@@ -85,8 +79,8 @@
{
Link link(Block(GOOD_LINK, sizeof(GOOD_LINK)));
BOOST_CHECK_EQUAL(link.getName(), Name("/local/ndn/prefix"));
- BOOST_CHECK_EQUAL(link.getDelegationList(),
- DelegationList({{10, Name("/local")}, {20, Name("/ndn")}}));
+ BOOST_TEST(link.getDelegationList() == std::vector<Name>({"/local", "/ndn"}),
+ boost::test_tools::per_element());
}
BOOST_AUTO_TEST_CASE(DecodeBadContentType)
@@ -102,14 +96,14 @@
BOOST_AUTO_TEST_CASE(Encode)
{
- Link link1("/test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
+ Link link1("/test", {"/test1", "/test2", "/test3"});
signData(link1);
Block wire = link1.wireEncode();
Link link2(wire);
BOOST_CHECK_EQUAL(link2.getName(), "/test");
- BOOST_CHECK_EQUAL(link2.getDelegationList(),
- DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+ BOOST_TEST(link2.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+ boost::test_tools::per_element());
}
BOOST_AUTO_TEST_SUITE_END() // EncodeDecode
@@ -119,54 +113,55 @@
BOOST_AUTO_TEST_CASE(SetDelegationList)
{
Link link("/test");
- BOOST_CHECK_EQUAL(link.getDelegationList(), DelegationList());
+ BOOST_CHECK(link.getDelegationList().empty());
- link.setDelegationList(DelegationList({{10, "/test1"}, {20, "/test2"}}));
- BOOST_CHECK_EQUAL(link.getDelegationList(), DelegationList({{10, "/test1"}, {20, "/test2"}}));
+ link.setDelegationList(std::vector<Name>({"/test1", "/test2"}));
+ BOOST_TEST(link.getDelegationList() == std::vector<Name>({"/test1", "/test2"}),
+ boost::test_tools::per_element());
}
BOOST_AUTO_TEST_CASE(AddDelegation)
{
- Link link1("/test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
- BOOST_CHECK_EQUAL(link1.getDelegationList(),
- DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+ Link link1("/test", {"/test1", "/test2", "/test3"});
+ BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+ boost::test_tools::per_element());
- link1.addDelegation(30, "/test4");
- BOOST_CHECK_EQUAL(link1.getDelegationList(),
- DelegationList({{10, "/test1"}, {20, "/test2"}, {30, "/test4"}, {100, "/test3"}}));
+ BOOST_CHECK(link1.addDelegation("/test4"));
+ BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3", "/test4"}),
+ boost::test_tools::per_element());
- link1.addDelegation(40, "/test2");
- BOOST_CHECK_EQUAL(link1.getDelegationList(),
- DelegationList({{10, "/test1"}, {30, "/test4"}, {40, "/test2"}, {100, "/test3"}}));
+ BOOST_CHECK(!link1.addDelegation("/test2"));
+ BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3", "/test4"}),
+ boost::test_tools::per_element());
signData(link1);
Link link2(link1.wireEncode());
- BOOST_CHECK_EQUAL(link2.getDelegationList(),
- DelegationList({{10, "/test1"}, {30, "/test4"}, {40, "/test2"}, {100, "/test3"}}));
+ BOOST_TEST(link2.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3", "/test4"}),
+ boost::test_tools::per_element());
}
BOOST_AUTO_TEST_CASE(RemoveDelegation)
{
- Link link1("/test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
- BOOST_CHECK_EQUAL(link1.getDelegationList(),
- DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+ Link link1("/test", {"/test1", "/test2", "/test3"});
+ BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+ boost::test_tools::per_element());
- link1.removeDelegation("/test4"); // non-existent
- BOOST_CHECK_EQUAL(link1.getDelegationList(),
- DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+ BOOST_CHECK(!link1.removeDelegation("/test4")); // non-existent
+ BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+ boost::test_tools::per_element());
- link1.removeDelegation("/test2");
- BOOST_CHECK_EQUAL(link1.getDelegationList(),
- DelegationList({{10, "/test1"}, {100, "/test3"}}));
+ BOOST_CHECK(link1.removeDelegation("/test2"));
+ BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test3"}),
+ boost::test_tools::per_element());
signData(link1);
Link link2(link1.wireEncode());
- BOOST_CHECK_EQUAL(link2.getDelegationList(),
- DelegationList({{10, "/test1"}, {100, "/test3"}}));
+ BOOST_TEST(link2.getDelegationList() == std::vector<Name>({"/test1", "/test3"}),
+ boost::test_tools::per_element());
link1.removeDelegation("/test1");
link1.removeDelegation("/test3");
- BOOST_CHECK_EQUAL(link1.getDelegationList(), DelegationList());
+ BOOST_CHECK(link1.getDelegationList().empty());
}
BOOST_AUTO_TEST_SUITE_END() // Modify