encoding: Optimized encoding of Interest and related data structures
Change-Id: I0609b40565835568e09c3cc0330db441fd9243b6
refs: #1172
diff --git a/src/interest.hpp b/src/interest.hpp
index 168cad1..842c427 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -1,7 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
* Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
@@ -10,17 +9,68 @@
#include "common.hpp"
#include "name.hpp"
-#include "exclude.hpp"
-#include "encoding/block.hpp"
+#include "selectors.hpp"
namespace ndn {
-
+
+const Milliseconds DEFAULT_INTEREST_LIFETIME = 4000;
+
/**
* An Interest holds a Name and other fields for an interest.
*/
-class Interest : public enable_shared_from_this<Interest> {
+class Interest : public enable_shared_from_this<Interest>
+{
public:
/**
+ * @brief Create a new Interest with an empty name and "none" for all values.
+ */
+ Interest()
+ : m_nonce(0)
+ , m_scope(-1)
+ , m_interestLifetime(-1.0)
+ {
+ }
+
+ /**
+ * @brief Create a new Interest with the given name and "none" for other values.
+ *
+ * @param name The name for the interest.
+ */
+ Interest(const Name& name)
+ : m_name(name)
+ , m_nonce(0)
+ , m_scope(-1)
+ , m_interestLifetime(-1.0)
+ {
+ }
+
+ /**
+ * Create a new Interest with the given name and interest lifetime and "none" for other values.
+ * @param name The name for the interest.
+ * @param interestLifetimeMilliseconds The interest lifetime in milliseconds, or -1 for none.
+ */
+ Interest(const Name& name, Milliseconds interestLifetime)
+ : m_name(name)
+ , m_nonce(0)
+ , m_scope(-1)
+ , m_interestLifetime(interestLifetime)
+ {
+ }
+
+ Interest(const Name& name,
+ const Selectors& selectors,
+ int scope,
+ Milliseconds interestLifetime,
+ uint32_t nonce = 0)
+ : m_name(name)
+ , m_selectors(selectors)
+ , m_nonce(nonce)
+ , m_scope(scope)
+ , m_interestLifetime(interestLifetime)
+ {
+ }
+
+ /**
* Create a new Interest for the given name and values.
* @param name
* @param minSuffixComponents
@@ -40,59 +90,31 @@
int scope,
Milliseconds interestLifetime,
uint32_t nonce = 0)
- : name_(name)
- , minSuffixComponents_(minSuffixComponents)
- , maxSuffixComponents_(maxSuffixComponents)
- , exclude_(exclude), childSelector_(childSelector)
- , mustBeFresh_(mustBeFresh)
- , scope_(scope)
- , interestLifetime_(interestLifetime)
- , nonce_(nonce)
+ : m_name(name)
+ , m_selectors(minSuffixComponents, maxSuffixComponents, exclude, childSelector, mustBeFresh)
+ , m_nonce(nonce)
+ , m_scope(scope)
+ , m_interestLifetime(interestLifetime)
{
}
/**
- * Create a new Interest with the given name and interest lifetime and "none" for other values.
- * @param name The name for the interest.
- * @param interestLifetimeMilliseconds The interest lifetime in milliseconds, or -1 for none.
+ * @brief Fast encoding or block size estimation
*/
- Interest(const Name& name, Milliseconds interestLifetime)
- : name_(name)
- {
- construct();
- interestLifetime_ = interestLifetime;
- }
-
- /**
- * Create a new Interest with the given name and "none" for other values.
- * @param name The name for the interest.
- */
- Interest(const Name& name)
- : name_(name)
- {
- construct();
- }
-
- /**
- * Create a new Interest with an empty name and "none" for all values.
- */
- Interest()
- {
- construct();
- }
+ template<bool T>
+ inline size_t
+ wireEncode(EncodingImpl<T> &block) const;
/**
- * Encode this Interest for a particular wire format.
- * @return The encoded byte array.
+ * @brief Encode to a wire format
*/
- const Block&
+ inline const Block&
wireEncode() const;
-
+
/**
- * Decode the input using a particular wire format and update this Interest.
- * @param input The input byte array to be decoded.
+ * @brief Decode from the wire format
*/
- void
+ inline void
wireDecode(const Block &wire);
/**
@@ -103,79 +125,6 @@
inline std::string
toUri() const;
- Name&
- getName() { return name_; }
-
- const Name&
- getName() const { return name_; }
-
- int
- getMinSuffixComponents() const { return minSuffixComponents_; }
-
- int
- getMaxSuffixComponents() const { return maxSuffixComponents_; }
-
- Exclude&
- getExclude() { return exclude_; }
-
- const Exclude&
- getExclude() const { return exclude_; }
-
- int
- getChildSelector() const { return childSelector_; }
-
- int
- getMustBeFresh() const { return mustBeFresh_; }
-
- int
- getScope() const { return scope_; }
-
- Milliseconds
- getInterestLifetime() const { return interestLifetime_; }
-
- /**
- * @brief Get Interest's nonce
- *
- * If nonce was not set before this call, it will be automatically assigned to a random value
- *
- * Const reference needed for C decoding
- */
- const uint32_t&
- getNonce() const;
-
- uint64_t
- getIncomingFaceId() const { return m_incomingFaceId; }
-
- void
- setName(const Name& name) { name_ = name; }
-
- void
- setMinSuffixComponents(int minSuffixComponents) { minSuffixComponents_ = minSuffixComponents; }
-
- void
- setMaxSuffixComponents(int maxSuffixComponents) { maxSuffixComponents_ = maxSuffixComponents; }
-
- void
- setExclude(const Exclude& exclude) { exclude_ = exclude; }
-
- void
- setChildSelector(int childSelector) { childSelector_ = childSelector; }
-
- void
- setMustBeFresh(bool mustBeFresh) { mustBeFresh_ = mustBeFresh; }
-
- void
- setScope(int scope) { scope_ = scope; }
-
- void
- setInterestLifetime(Milliseconds interestLifetime) { interestLifetime_ = interestLifetime; }
-
- void
- setNonce(uint32_t nonce) { nonce_ = nonce; }
-
- void
- setIncomingFaceId(uint64_t incomingFaceId) { m_incomingFaceId = incomingFaceId; }
-
inline bool
hasSelectors() const;
@@ -191,31 +140,205 @@
*/
bool
matchesName(const Name &name) const;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+ // Gettest/setters
-private:
- void
- construct()
+ const Name&
+ getName() const
{
- minSuffixComponents_ = -1;
- maxSuffixComponents_ = -1;
- childSelector_ = -1;
- mustBeFresh_ = false; // default
- scope_ = -1;
- interestLifetime_ = -1.0;
- nonce_ = 0;
+ return m_name;
+ }
+
+ Interest&
+ setName(const Name& name)
+ {
+ m_name = name;
+ m_wire.reset();
+ return *this;
}
- Name name_;
- int minSuffixComponents_;
- int maxSuffixComponents_;
- Exclude exclude_;
- int childSelector_;
- bool mustBeFresh_;
- int scope_;
- Milliseconds interestLifetime_;
- mutable uint32_t nonce_;
+ //
- mutable Block wire_;
+ const Selectors&
+ getSelectors() const
+ {
+ return m_selectors;
+ }
+
+ Interest&
+ setSelectors(const Selectors& selectors)
+ {
+ m_selectors = selectors;
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getScope() const
+ {
+ return m_scope;
+ }
+
+ Interest&
+ setScope(int scope)
+ {
+ m_scope = scope;
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ Milliseconds
+ getInterestLifetime() const
+ {
+ return m_interestLifetime;
+ }
+
+ Interest&
+ setInterestLifetime(Milliseconds interestLifetime)
+ {
+ m_interestLifetime = interestLifetime;
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ /**
+ * @brief Get Interest's nonce
+ *
+ * If nonce was not set before this call, it will be automatically assigned to a random value
+ *
+ * Const reference needed for C decoding
+ */
+ const uint32_t&
+ getNonce() const;
+
+ Interest&
+ setNonce(uint32_t nonce)
+ {
+ m_nonce = nonce;
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ uint64_t
+ getIncomingFaceId() const
+ {
+ return m_incomingFaceId;
+ }
+
+ Interest&
+ setIncomingFaceId(uint64_t incomingFaceId)
+ {
+ m_incomingFaceId = incomingFaceId;
+ return *this;
+ }
+
+ //
+
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+ // Wrappers for Selectors
+ //
+
+ int
+ getMinSuffixComponents() const
+ {
+ return m_selectors.getMinSuffixComponents();
+ }
+
+ Interest&
+ setMinSuffixComponents(int minSuffixComponents)
+ {
+ m_selectors.setMinSuffixComponents(minSuffixComponents);
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getMaxSuffixComponents() const
+ {
+ return m_selectors.getMaxSuffixComponents();
+ }
+
+ Interest&
+ setMaxSuffixComponents(int maxSuffixComponents)
+ {
+ m_selectors.setMaxSuffixComponents(maxSuffixComponents);
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ const Exclude&
+ getExclude() const
+ {
+ return m_selectors.getExclude();
+ }
+
+ Interest&
+ setExclude(const Exclude& exclude)
+ {
+ m_selectors.setExclude(exclude);
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getChildSelector() const
+ {
+ return m_selectors.getChildSelector();
+ }
+
+ Interest&
+ setChildSelector(int childSelector)
+ {
+ m_selectors.setChildSelector(childSelector);
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getMustBeFresh() const
+ {
+ return m_selectors.getMustBeFresh();
+ }
+
+ Interest&
+ setMustBeFresh(bool mustBeFresh)
+ {
+ m_selectors.setMustBeFresh(mustBeFresh);
+ m_wire.reset();
+ return *this;
+ }
+
+ //
+
+private:
+ Name m_name;
+ Selectors m_selectors;
+ mutable uint32_t m_nonce;
+ int m_scope;
+ Milliseconds m_interestLifetime;
+
+ mutable Block m_wire;
uint64_t m_incomingFaceId;
};
@@ -234,22 +357,136 @@
inline bool
Interest::hasSelectors() const
{
- return minSuffixComponents_ >= 0 ||
- maxSuffixComponents_ >= 0 ||
- !exclude_.empty() ||
- childSelector_ >= 0 ||
- mustBeFresh_ == true ||
- scope_ >= 0;
+ return !m_selectors.empty();
}
inline bool
Interest::hasGuiders() const
{
- return scope_ >= 0 ||
- interestLifetime_ >= 0 ||
- nonce_ > 0;
+ return m_scope >= 0 ||
+ m_interestLifetime >= 0 ||
+ m_nonce > 0;
}
+template<bool T>
+inline size_t
+Interest::wireEncode(EncodingImpl<T> &block) const
+{
+ size_t total_len = 0;
+
+ // Interest ::= INTEREST-TYPE TLV-LENGTH
+ // Name
+ // Selectors?
+ // Nonce
+ // Scope?
+ // InterestLifetime?
+
+ // (reverse encoding)
+
+ // InterestLifetime
+ if (getInterestLifetime() >= 0 && getInterestLifetime() != DEFAULT_INTEREST_LIFETIME)
+ {
+ total_len += prependNonNegativeIntegerBlock(block, Tlv::InterestLifetime, getInterestLifetime());
+ }
+
+ // Scope
+ if (getScope() >= 0)
+ {
+ total_len += prependNonNegativeIntegerBlock(block, Tlv::Scope, getScope());
+ }
+
+ // Nonce
+ total_len += prependNonNegativeIntegerBlock(block, Tlv::Nonce, getNonce());
+
+ // Selectors
+ if (!getSelectors().empty())
+ {
+ total_len += getSelectors().wireEncode(block);
+ }
+
+ // Name
+ total_len += getName().wireEncode(block);
+
+ total_len += block.prependVarNumber (total_len);
+ total_len += block.prependVarNumber (Tlv::Interest);
+ return total_len;
}
-#endif
+inline const Block &
+Interest::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+inline void
+Interest::wireDecode(const Block &wire)
+{
+ m_wire = wire;
+ m_wire.parse();
+
+ // Interest ::= INTEREST-TYPE TLV-LENGTH
+ // Name
+ // Selectors?
+ // Nonce
+ // Scope?
+ // InterestLifetime?
+
+ if (m_wire.type() != Tlv::Interest)
+ throw Tlv::Error("Unexpected TLV number when decoding Interest");
+
+ // Name
+ m_name.wireDecode(m_wire.get(Tlv::Name));
+
+ // Selectors
+ Block::element_const_iterator val = m_wire.find(Tlv::Selectors);
+ if (val != m_wire.elements_end())
+ {
+ m_selectors.wireDecode(*val);
+ }
+ else
+ m_selectors = Selectors();
+
+ // Nonce
+ val = m_wire.find(Tlv::Nonce);
+ if (val != m_wire.elements_end())
+ {
+ m_nonce = readNonNegativeInteger(*val);
+ }
+ else
+ m_nonce = 0;
+
+ // Scope
+ val = m_wire.find(Tlv::Scope);
+ if (val != m_wire.elements_end())
+ {
+ m_scope = readNonNegativeInteger(*val);
+ }
+ else
+ m_scope = -1;
+
+ // InterestLifetime
+ val = m_wire.find(Tlv::InterestLifetime);
+ if (val != m_wire.elements_end())
+ {
+ m_interestLifetime = readNonNegativeInteger(*val);
+ }
+ else
+ {
+ m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
+ }
+}
+
+
+} // namespace ndn
+
+#endif // NDN_INTEREST_HPP