interest: Add Link and SelectedDelegation fields
Change-Id: I1e4bafe8559ef87135de6cb6f209fc94dfa231b0
Refs: #2587
diff --git a/src/interest.cpp b/src/interest.cpp
index 0ae0852..017711a 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -36,6 +36,7 @@
Interest::Interest()
: m_scope(-1)
, m_interestLifetime(time::milliseconds::min())
+ , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
{
}
@@ -43,6 +44,7 @@
: m_name(name)
, m_scope(-1)
, m_interestLifetime(time::milliseconds::min())
+ , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
{
}
@@ -50,6 +52,7 @@
: m_name(name)
, m_scope(-1)
, m_interestLifetime(interestLifetime)
+ , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
{
}
@@ -62,6 +65,7 @@
, m_selectors(selectors)
, m_scope(scope)
, m_interestLifetime(interestLifetime)
+ , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
{
if (nonce > 0) {
setNonce(nonce);
@@ -239,9 +243,23 @@
// Nonce
// Scope?
// InterestLifetime?
+ // Link?
+ // SelectedDelegation?
// (reverse encoding)
+ if (hasLink()) {
+ if (hasSelectedDelegation()) {
+ totalLength += prependNonNegativeIntegerBlock(block,
+ tlv::SelectedDelegation,
+ m_selectedDelegationIndex);
+ }
+ totalLength += prependBlock(block, m_link);
+ }
+ else {
+ BOOST_ASSERT(!hasSelectedDelegation());
+ }
+
// InterestLifetime
if (getInterestLifetime() >= time::milliseconds::zero() &&
getInterestLifetime() != DEFAULT_INTEREST_LIFETIME)
@@ -311,6 +329,8 @@
// Nonce
// Scope?
// InterestLifetime?
+ // Link?
+ // SelectedDelegation?
if (m_wire.type() != tlv::Interest)
throw Error("Unexpected TLV number when decoding Interest");
@@ -349,6 +369,114 @@
{
m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
}
+
+ // Link object
+ val = m_wire.find(tlv::Data);
+ if (val != m_wire.elements_end())
+ {
+ m_link = (*val);
+ }
+
+ // SelectedDelegation
+ val = m_wire.find(tlv::SelectedDelegation);
+ if (val != m_wire.elements_end()) {
+ if (!this->hasLink()) {
+ throw Error("Interest contains selectedDelegation, but no LINK object");
+ }
+ uint64_t selectedDelegation = readNonNegativeInteger(*val);
+ if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
+ m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
+ }
+ else {
+ throw Error("Invalid selected delegation index when decoding Interest");
+ }
+ }
+}
+
+bool
+Interest::hasLink() const
+{
+ if (m_link.hasWire())
+ return true;
+ return false;
+}
+
+Link
+Interest::getLink() const
+{
+ if (hasLink())
+ {
+ return Link(m_link);
+ }
+ throw Error("There is no encapsulated link object");
+}
+
+void
+Interest::setLink(const Block& link)
+{
+ m_link = link;
+ if (!link.hasWire()) {
+ throw Error("The given link does not have a wire format");
+ }
+ m_wire.reset();
+ this->unsetSelectedDelegation();
+}
+
+void
+Interest::unsetLink()
+{
+ m_link.reset();
+ m_wire.reset();
+ this->unsetSelectedDelegation();
+}
+
+bool
+Interest::hasSelectedDelegation() const
+{
+ if (m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX)
+ {
+ return true;
+ }
+ return false;
+}
+
+Name
+Interest::getSelectedDelegation() const
+{
+ if (!hasSelectedDelegation()) {
+ throw Error("There is no encapsulated selected delegation");
+ }
+ return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
+}
+
+void
+Interest::setSelectedDelegation(const Name& delegationName)
+{
+ size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
+ if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
+ m_selectedDelegationIndex = delegationIndex;
+ }
+ else {
+ throw std::invalid_argument("Invalid selected delegation name");
+ }
+ m_wire.reset();
+}
+
+void
+Interest::setSelectedDelegation(size_t delegationIndex)
+{
+ if (delegationIndex >= Link(m_link).getDelegations().size()) {
+ throw Error("Invalid selected delegation index");
+ }
+ m_selectedDelegationIndex = delegationIndex;
+ m_wire.reset();
+}
+
+void
+Interest::unsetSelectedDelegation()
+{
+ m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
+ m_wire.reset();
}
std::ostream&
diff --git a/src/interest.hpp b/src/interest.hpp
index 48f34f7..1e064fb 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -29,6 +29,7 @@
#include "util/time.hpp"
#include "management/nfd-local-control-header.hpp"
#include "tag-host.hpp"
+#include "link.hpp"
namespace ndn {
@@ -130,6 +131,76 @@
std::string
toUri() const;
+public: // Link and forwarding hint
+
+ /**
+ * @brief Check whether the Interest contains a Link object
+ * @return True if there is a link object, otherwise false
+ */
+ bool
+ hasLink() const;
+
+ /**
+ * @brief Get the link object for this interest
+ * @return The link object if there is one contained in this interest
+ * @throws Interest::Error if there is no link object contained in the interest
+ */
+ Link
+ getLink() const;
+
+ /**
+ * @brief Set the link object for this interest
+ * @param link The link object that will be included in this interest (in wire format)
+ * @post !hasSelectedDelegation()
+ */
+ void
+ setLink(const Block& link);
+
+ /**
+ *@brief Reset the wire format of the given interest and the contained link
+ */
+ void
+ unsetLink();
+
+ /**
+ * @brief Check whether the Interest includes a selected delegation
+ * @return True if there is a selected delegation, otherwise false
+ */
+ bool
+ hasSelectedDelegation() const;
+
+ /**
+ * @brief Get the name of the selected delegation
+ * @return The name of the selected delegation
+ * @throw Error SelectedDelegation is not set.
+ */
+ Name
+ getSelectedDelegation() const;
+
+ /**
+ * @brief Set the selected delegation
+ * @param delegationName The name of the selected delegation
+ * @throw Error Link is not set.
+ * @throw std::invalid_argument @p delegationName does not exist in Link.
+ */
+ void
+ setSelectedDelegation(const Name& delegationName);
+
+ /**
+ * @brief Set the selected delegation
+ * @param delegation The index of the selected delegation
+ * @throw Error Link is not set.
+ * @throw std::out_of_range @p delegationIndex is out of bound in Link.
+ */
+ void
+ setSelectedDelegation(size_t delegationIndex);
+
+ /**
+ * @brief Unset the selected delegation
+ */
+ void
+ unsetSelectedDelegation();
+
public: // matching
/** @brief Check if Interest, including selectors, matches the given @p name
* @param name The name to be matched. If this is a Data name, it shall contain the
@@ -395,6 +466,8 @@
int m_scope;
time::milliseconds m_interestLifetime;
+ mutable Block m_link;
+ size_t m_selectedDelegationIndex;
mutable Block m_wire;
nfd::LocalControlHeader m_localControlHeader;
diff --git a/src/link.cpp b/src/link.cpp
index 07ac0d9..ce05b36 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -179,6 +179,53 @@
decodeContent();
}
+std::tuple<uint32_t, Name>
+Link::getDelegationFromWire(const Block& block, size_t index)
+{
+ block.parse();
+ const Block& contentBlock = block.get(tlv::Content);
+ contentBlock.parse();
+ const Block& delegationBlock = contentBlock.elements().at(index);
+ delegationBlock.parse();
+ if (delegationBlock.type() != tlv::LinkDelegation) {
+ throw Error("Unexpected TLV-TYPE; expecting LinkDelegation");
+ }
+ return std::make_tuple(
+ static_cast<uint32_t>(
+ readNonNegativeInteger(delegationBlock.get(tlv::LinkPreference))),
+ Name(delegationBlock.get(tlv::Name)));
+}
+
+ssize_t
+Link::findDelegationFromWire(const Block& block, const Name& delegationName)
+{
+ block.parse();
+ const Block& contentBlock = block.get(tlv::Content);
+ contentBlock.parse();
+ size_t counter = 0;
+ for (auto&& delegationBlock : contentBlock.elements()) {
+ delegationBlock.parse();
+ if (delegationBlock.type() != tlv::LinkDelegation) {
+ throw Error("Unexpected TLV-TYPE; expecting LinkDelegation");
+ }
+ Name name(delegationBlock.get(tlv::Name));
+ if (name == delegationName) {
+ return counter;
+ }
+ ++counter;
+ }
+ return INVALID_SELECTED_DELEGATION_INDEX;
+}
+
+ssize_t
+Link::countDelegationsFromWire(const Block& block)
+{
+ block.parse();
+ const Block& contentBlock = block.get(tlv::Content);
+ contentBlock.parse();
+ return contentBlock.elements_size();
+}
+
bool
Link::removeDelegationNoEncode(const Name& name)
{
diff --git a/src/link.hpp b/src/link.hpp
index 3ccb7a3..e4e9f38 100644
--- a/src/link.hpp
+++ b/src/link.hpp
@@ -129,12 +129,34 @@
/**
* @brief Decode from the wire format
+ * @warning This method does not preserve the relative order between delegations.
+ * To get a delegation by index, use \p getDelegationFromWire method.
*/
void
wireDecode(const Block& wire);
+ /** @brief gets the delegation at \p index from \p block
+ * @param block wire format of a Link object
+ * @param index 0-based index of a delegation in the Link object
+ * @return delegation preference and name
+ * @throw std::out_of_range index is out of range
+ */
+ static std::tuple<uint32_t, Name>
+ getDelegationFromWire(const Block& block, size_t index);
+
+ /** @brief finds index of a delegation with \p delegationName from \p block
+ * @param block wire format of a Link object
+ * @return 0-based index of the first delegation with \p delegationName ,
+ * or -1 if no such delegation exists
+ */
+ static ssize_t
+ findDelegationFromWire(const Block& block, const Name& delegationName);
+
+ static ssize_t
+ countDelegationsFromWire(const Block& block);
+
protected:
- /** \brief prepend Link object as a Content block to the encoder
+ /** @brief prepend Link object as a Content block to the encoder
*
* The outermost Content element is not part of Link object structure.
*/