encoding: Optimized encoding of Interest and related data structures
Change-Id: I0609b40565835568e09c3cc0330db441fd9243b6
refs: #1172
diff --git a/src/detail/registered-prefix.hpp b/src/detail/registered-prefix.hpp
index aeb6c66..02a0ed7 100644
--- a/src/detail/registered-prefix.hpp
+++ b/src/detail/registered-prefix.hpp
@@ -8,6 +8,7 @@
#define NDN_DETAIL_REGISTERED_PREFIX_HPP
#include "../common.hpp"
+#include "../name.hpp"
#include "../interest.hpp"
namespace ndn {
diff --git a/src/encoding/encoding-buffer.hpp b/src/encoding/encoding-buffer.hpp
index fe5dc3a..7385c65 100644
--- a/src/encoding/encoding-buffer.hpp
+++ b/src/encoding/encoding-buffer.hpp
@@ -496,6 +496,44 @@
return prependVarNumber(varNumber);
}
+/// helper methods
+
+template<bool P>
+inline size_t
+prependNonNegativeIntegerBlock(EncodingImpl<P>& blk, uint32_t type, uint64_t number)
+{
+ size_t var_len = blk.prependNonNegativeInteger(number);
+ size_t total_len = var_len;
+ total_len += blk.prependVarNumber(var_len);
+ total_len += blk.prependVarNumber(type);
+
+ return total_len;
+}
+
+template<bool P>
+inline size_t
+prependBooleanBlock(EncodingImpl<P>& blk, uint32_t type)
+{
+ size_t total_len = blk.prependVarNumber(0);
+ total_len += blk.prependVarNumber(type);
+
+ return total_len;
+}
+
+
+template<bool P, class U>
+inline size_t
+prependNestedBlock(EncodingImpl<P>& blk, uint32_t type, U& nestedBlock)
+{
+ size_t var_len = nestedBlock.wireEncode(blk);
+ size_t total_len = var_len;
+ total_len += blk.prependVarNumber(var_len);
+ total_len += blk.prependVarNumber(type);
+
+ return total_len;
+}
+
+
} // ndn
#endif // NDN_ENCODING_BUFFER_HPP
diff --git a/src/exclude.cpp b/src/exclude.cpp
index 983daaf..bc1f9d5 100644
--- a/src/exclude.cpp
+++ b/src/exclude.cpp
@@ -32,7 +32,7 @@
// lower_bound (/d) -> /d (true) <- excluded
// lower_bound (/e) -> /d (true) <- excluded
bool
-Exclude::isExcluded (const Name::Component &comp) const
+Exclude::isExcluded (const name::Component &comp) const
{
const_iterator lowerBound = m_exclude.lower_bound (comp);
if (lowerBound == end ())
@@ -47,7 +47,7 @@
}
Exclude &
-Exclude::excludeOne (const Name::Component &comp)
+Exclude::excludeOne (const name::Component &comp)
{
if (!isExcluded (comp))
{
@@ -85,7 +85,7 @@
// /f0 (false); /d0 (true); /c0 (false); /b1 (true); /b0 (false); / (true)
Exclude &
-Exclude::excludeRange (const Name::Component &from, const Name::Component &to)
+Exclude::excludeRange (const name::Component &from, const name::Component &to)
{
if (from >= to)
{
@@ -127,7 +127,7 @@
}
Exclude &
-Exclude::excludeAfter (const Name::Component &from)
+Exclude::excludeAfter (const name::Component &from)
{
iterator newFrom = m_exclude.lower_bound (from);
if (newFrom == end () || !newFrom->second /*without ANY*/)
@@ -174,78 +174,5 @@
return os;
}
-const Block&
-Exclude::wireEncode() const
-{
- if (wire_.hasWire())
- return wire_;
-
- wire_ = Block(Tlv::Exclude);
-
- for (Exclude::const_reverse_iterator i = m_exclude.rbegin (); i != m_exclude.rend (); i++)
- {
- if (!i->first.empty())
- {
- OBufferStream os;
- Tlv::writeVarNumber(os, Tlv::NameComponent);
- Tlv::writeVarNumber(os, i->first.value_size());
- os.write(reinterpret_cast<const char *>(i->first.value()), i->first.value_size());
-
- wire_.push_back(Block(os.buf()));
-
- }
- if (i->second)
- {
- OBufferStream os;
- Tlv::writeVarNumber(os, Tlv::Any);
- Tlv::writeVarNumber(os, 0);
- wire_.push_back(Block(os.buf()));
- }
- }
-
- wire_.encode();
- return wire_;
-}
-
-void
-Exclude::wireDecode(const Block &wire)
-{
- wire_ = wire;
- wire_.parse();
-
- Block::element_const_iterator i = wire_.elements_begin();
- if (i->type() == Tlv::Any)
- {
- appendExclude(name::Component(), true);
- ++i;
- }
-
- while (i != wire_.elements_end())
- {
- if (i->type() != Tlv::NameComponent)
- throw Error("Incorrect format of Exclude filter");
-
- Name::Component excludedComponent (i->value(), i->value_size());
- ++i;
-
- if (i != wire_.elements_end())
- {
- if (i->type() == Tlv::Any)
- {
- appendExclude(excludedComponent, true);
- ++i;
- }
- else
- {
- appendExclude(excludedComponent, false);
- }
- }
- else
- {
- appendExclude(excludedComponent, false);
- }
- }
-}
-
} // ndn
diff --git a/src/exclude.hpp b/src/exclude.hpp
index 62ce672..22dc929 100644
--- a/src/exclude.hpp
+++ b/src/exclude.hpp
@@ -11,7 +11,7 @@
#ifndef NDN_EXCLUDE_H
#define NDN_EXCLUDE_H
-#include "name.hpp"
+#include "name-component.hpp"
namespace ndn {
@@ -24,7 +24,7 @@
struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
- typedef std::map< Name::Component, bool /*any*/, std::greater<Name::Component> > exclude_type;
+ typedef std::map< name::Component, bool /*any*/, std::greater<name::Component> > exclude_type;
typedef exclude_type::iterator iterator;
typedef exclude_type::const_iterator const_iterator;
@@ -37,11 +37,33 @@
Exclude ();
/**
+ * @brief Fast encoding or block size estimation
+ */
+ template<bool T>
+ inline size_t
+ wireEncode(EncodingImpl<T> &block) const;
+
+ /**
+ * @brief Encode to a wire format
+ */
+ inline const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode from the wire format
+ */
+ inline void
+ wireDecode(const Block &wire);
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+
+ /**
* @brief Check if name component is excluded
* @param comp Name component to check against exclude filter
*/
bool
- isExcluded (const Name::Component &comp) const;
+ isExcluded (const name::Component &comp) const;
/**
* @brief Exclude specific name component
@@ -49,7 +71,7 @@
* @returns *this to allow chaining
*/
Exclude &
- excludeOne (const Name::Component &comp);
+ excludeOne (const name::Component &comp);
/**
* @brief Exclude components from range [from, to]
@@ -58,7 +80,7 @@
* @returns *this to allow chaining
*/
Exclude &
- excludeRange (const Name::Component &from, const Name::Component &to);
+ excludeRange (const name::Component &from, const name::Component &to);
/**
* @brief Exclude all components from range [/, to]
@@ -66,7 +88,7 @@
* @returns *this to allow chaining
*/
inline Exclude &
- excludeBefore (const Name::Component &to);
+ excludeBefore (const name::Component &to);
/**
* @brief Exclude all components from range [from, +Inf]
@@ -74,7 +96,7 @@
* @returns *this to allow chaining
*/
Exclude &
- excludeAfter (const Name::Component &from);
+ excludeAfter (const name::Component &from);
/**
* @brief Method to directly append exclude element
@@ -86,7 +108,7 @@
* If there is an error with ranges (e.g., order of components is wrong) an exception is thrown
*/
inline void
- appendExclude (const Name::Component &name, bool any);
+ appendExclude (const name::Component &name, bool any);
/**
* @brief Check if exclude filter is empty
@@ -136,20 +158,6 @@
inline std::string
toUri () const;
- /**
- * Encode this Interest for a particular wire format.
- * @return The encoded byte array.
- */
- 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.
- */
- void
- wireDecode(const Block &wire);
-
private:
Exclude &
excludeRange (iterator fromLowerBound, iterator toLowerBound);
@@ -164,13 +172,13 @@
operator << (std::ostream &os, const Exclude &name);
inline Exclude &
-Exclude::excludeBefore (const Name::Component &to)
+Exclude::excludeBefore (const name::Component &to)
{
- return excludeRange (Name::Component (), to);
+ return excludeRange (name::Component (), to);
}
inline void
-Exclude::appendExclude (const Name::Component &name, bool any)
+Exclude::appendExclude (const name::Component &name, bool any)
{
m_exclude[name] = any;
}
@@ -226,6 +234,92 @@
return os.str();
}
+template<bool T>
+inline size_t
+Exclude::wireEncode(EncodingImpl<T> &block) const
+{
+ size_t total_len = 0;
+
+ // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
+ // Any ::= ANY-TYPE TLV-LENGTH(=0)
+
+ for (Exclude::const_iterator i = m_exclude.begin (); i != m_exclude.end (); i++)
+ {
+ if (i->second)
+ {
+ total_len += prependBooleanBlock(block, Tlv::Any);
+ }
+ if (!i->first.empty())
+ {
+ total_len += i->first.wireEncode(block);
+ }
+ }
+
+ total_len += block.prependVarNumber(total_len);
+ total_len += block.prependVarNumber(Tlv::Exclude);
+ return total_len;
+}
+
+inline const Block &
+Exclude::wireEncode() const
+{
+ if (wire_.hasWire())
+ return wire_;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ wire_ = buffer.block();
+ return wire_;
+}
+
+inline void
+Exclude::wireDecode(const Block &wire)
+{
+ wire_ = wire;
+ wire_.parse();
+
+ // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
+ // Any ::= ANY-TYPE TLV-LENGTH(=0)
+
+ Block::element_const_iterator i = wire_.elements_begin();
+ if (i->type() == Tlv::Any)
+ {
+ appendExclude(name::Component(), true);
+ ++i;
+ }
+
+ while (i != wire_.elements_end())
+ {
+ if (i->type() != Tlv::NameComponent)
+ throw Error("Incorrect format of Exclude filter");
+
+ name::Component excludedComponent (i->value(), i->value_size());
+ ++i;
+
+ if (i != wire_.elements_end())
+ {
+ if (i->type() == Tlv::Any)
+ {
+ appendExclude(excludedComponent, true);
+ ++i;
+ }
+ else
+ {
+ appendExclude(excludedComponent, false);
+ }
+ }
+ else
+ {
+ appendExclude(excludedComponent, false);
+ }
+ }
+}
+
+
} // ndn
#endif // NDN_EXCLUDE_H
diff --git a/src/helper/command-interest-generator.cpp b/src/helper/command-interest-generator.cpp
index c216680..006d440 100644
--- a/src/helper/command-interest-generator.cpp
+++ b/src/helper/command-interest-generator.cpp
@@ -28,8 +28,12 @@
usleep(1000); //Guarantee unqiueness of timestamp
timestamp = time::now();
}
-
- interest.getName().append(name::Component::fromNumber(timestamp)).append(name::Component::fromNumber(random::generateWord64()));
+
+ Name commandInterestName = interest.getName();
+ commandInterestName
+ .append(name::Component::fromNumber(timestamp))
+ .append(name::Component::fromNumber(random::generateWord64()));
+ interest.setName(commandInterestName);
if(certificateName == DEFAULT_CERTIFICATE_NAME)
m_keyChain.sign(interest);
@@ -45,8 +49,12 @@
int64_t timestamp = time::now() / 1000000;
if(timestamp <= m_lastTimestamp)
timestamp = m_lastTimestamp + 1;
-
- interest.getName().append(name::Component::fromNumber(timestamp)).append(name::Component::fromNumber(random::generateWord64()));
+
+ Name commandInterestName = interest.getName();
+ commandInterestName
+ .append(name::Component::fromNumber(timestamp))
+ .append(name::Component::fromNumber(random::generateWord64()));
+ interest.setName(commandInterestName);
m_keyChain.signByIdentity(interest, identity);
diff --git a/src/interest.cpp b/src/interest.cpp
index 99e5040..942a5f7 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -14,36 +14,34 @@
namespace ndn {
-const Milliseconds DEFAULT_INTEREST_LIFETIME = 4000;
-
const uint32_t&
Interest::getNonce() const
{
- if (nonce_ == 0)
- nonce_ = random::generateWord32();
+ if (m_nonce == 0)
+ m_nonce = random::generateWord32();
- return nonce_;
+ return m_nonce;
}
bool
Interest::matchesName(const Name &name) const
{
- if (!name_.isPrefixOf(name))
+ if (!m_name.isPrefixOf(name))
return false;
- if (minSuffixComponents_ >= 0 &&
+ if (getMinSuffixComponents() >= 0 &&
// Add 1 for the implicit digest.
- !(name.size() + 1 - name_.size() >= minSuffixComponents_))
+ !(name.size() + 1 - m_name.size() >= getMinSuffixComponents()))
return false;
- if (maxSuffixComponents_ >= 0 &&
+ if (getMaxSuffixComponents() >= 0 &&
// Add 1 for the implicit digest.
- !(name.size() + 1 - name_.size() <= maxSuffixComponents_))
+ !(name.size() + 1 - m_name.size() <= getMaxSuffixComponents()))
return false;
- if (!exclude_.empty() && name.size() > name_.size() &&
- exclude_.isExcluded(name[name_.size()]))
+ if (!getExclude().empty() && name.size() > m_name.size() &&
+ getExclude().isExcluded(name[m_name.size()]))
return false;
return true;
@@ -93,159 +91,4 @@
return os;
}
-const Block&
-Interest::wireEncode() const
-{
- if (wire_.hasWire())
- return wire_;
-
- // Interest ::= INTEREST-TYPE TLV-LENGTH
- // Name
- // Selectors?
- // Nonce
- // Scope?
- // InterestLifetime?
-
- wire_ = Block(Tlv::Interest);
- wire_.push_back(getName().wireEncode());
-
- // selectors
- {
- Block selectors(Tlv::Selectors);
-
- if (getMinSuffixComponents() >= 0) {
- selectors.push_back
- (nonNegativeIntegerBlock(Tlv::MinSuffixComponents, getMinSuffixComponents()));
- }
- if (getMaxSuffixComponents() >= 0) {
- selectors.push_back
- (nonNegativeIntegerBlock(Tlv::MaxSuffixComponents, getMaxSuffixComponents()));
- }
- if (!getExclude().empty()) {
- selectors.push_back
- (getExclude().wireEncode());
- }
- if (getChildSelector() >= 0) {
- selectors.push_back
- (nonNegativeIntegerBlock(Tlv::ChildSelector, getChildSelector()));
- }
- if (getMustBeFresh()) {
- selectors.push_back
- (booleanBlock(Tlv::MustBeFresh));
- }
-
- if (!selectors.elements().empty())
- {
- selectors.encode();
- wire_.push_back(selectors);
- }
- }
-
- // Nonce
- {
- wire_.push_back
- (nonNegativeIntegerBlock(Tlv::Nonce, getNonce()));
- }
-
- // Scope
- if (getScope() >= 0) {
- wire_.push_back
- (nonNegativeIntegerBlock(Tlv::Scope, getScope()));
- }
-
- // InterestLifetime
- if (getInterestLifetime() >= 0 && getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
- wire_.push_back
- (nonNegativeIntegerBlock(Tlv::InterestLifetime, getInterestLifetime()));
- }
-
- wire_.encode();
- return wire_;
-}
-
-void
-Interest::wireDecode(const Block &wire)
-{
- wire_ = wire;
- wire_.parse();
-
- // Interest ::= INTEREST-TYPE TLV-LENGTH
- // Name
- // Selectors?
- // Nonce
- // Scope?
- // InterestLifetime?
-
- // Name
- name_.wireDecode(wire_.get(Tlv::Name));
-
- // Selectors
- Block::element_const_iterator selectors = wire_.find(Tlv::Selectors);
- if (selectors != wire_.elements_end())
- {
- selectors->parse();
-
- // MinSuffixComponents
- Block::element_const_iterator val = selectors->find(Tlv::MinSuffixComponents);
- if (val != selectors->elements_end())
- {
- minSuffixComponents_ = readNonNegativeInteger(*val);
- }
-
- // MaxSuffixComponents
- val = selectors->find(Tlv::MaxSuffixComponents);
- if (val != selectors->elements_end())
- {
- maxSuffixComponents_ = readNonNegativeInteger(*val);
- }
-
- // Exclude
- val = selectors->find(Tlv::Exclude);
- if (val != selectors->elements_end())
- {
- exclude_.wireDecode(*val);
- }
-
- // ChildSelector
- val = selectors->find(Tlv::ChildSelector);
- if (val != selectors->elements_end())
- {
- childSelector_ = readNonNegativeInteger(*val);
- }
-
- //MustBeFresh aka AnswerOriginKind
- val = selectors->find(Tlv::MustBeFresh);
- if (val != selectors->elements_end())
- {
- mustBeFresh_ = true;
- }
- }
-
- // Nonce
- Block::element_const_iterator val = wire_.find(Tlv::Nonce);
- if (val != wire_.elements_end())
- {
- nonce_ = readNonNegativeInteger(*val);
- }
-
- // Scope
- val = wire_.find(Tlv::Scope);
- if (val != wire_.elements_end())
- {
- scope_ = readNonNegativeInteger(*val);
- }
-
- // InterestLifetime
- val = wire_.find(Tlv::InterestLifetime);
- if (val != wire_.elements_end())
- {
- interestLifetime_ = readNonNegativeInteger(*val);
- }
- else
- {
- interestLifetime_ = DEFAULT_INTEREST_LIFETIME;
- }
-}
-
-
}
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
diff --git a/src/meta-info.hpp b/src/meta-info.hpp
index fc5458e..ff71570 100644
--- a/src/meta-info.hpp
+++ b/src/meta-info.hpp
@@ -33,6 +33,19 @@
{
wireDecode(block);
}
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T> &block) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block &wire);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Gettest/setters
uint32_t
getType() const
@@ -76,16 +89,6 @@
return *this;
}
- template<bool T>
- size_t
- wireEncode(EncodingImpl<T> &block) const;
-
- const Block&
- wireEncode() const;
-
- void
- wireDecode(const Block &wire);
-
private:
uint32_t m_type;
Milliseconds m_freshnessPeriod;
@@ -108,28 +111,19 @@
// FinalBlockId
if (!m_finalBlockId.empty())
{
- size_t var_len = m_finalBlockId.wireEncode (blk);
- total_len += var_len;
- total_len += blk.prependVarNumber (var_len);
- total_len += blk.prependVarNumber (Tlv::FinalBlockId);
+ total_len += prependNestedBlock(blk, Tlv::FinalBlockId, m_finalBlockId);
}
// FreshnessPeriod
if (m_freshnessPeriod >= 0)
{
- size_t var_len = blk.prependNonNegativeInteger (m_freshnessPeriod);
- total_len += var_len;
- total_len += blk.prependVarNumber (var_len);
- total_len += blk.prependVarNumber (Tlv::FreshnessPeriod);
+ total_len += prependNonNegativeIntegerBlock(blk, Tlv::FreshnessPeriod, m_freshnessPeriod);
}
// ContentType
if (m_type != TYPE_DEFAULT)
{
- size_t var_len = blk.prependNonNegativeInteger (m_type);
- total_len += var_len;
- total_len += blk.prependVarNumber (var_len);
- total_len += blk.prependVarNumber (Tlv::ContentType);
+ total_len += prependNonNegativeIntegerBlock(blk, Tlv::ContentType, m_type);
}
total_len += blk.prependVarNumber (total_len);
diff --git a/src/name.hpp b/src/name.hpp
index f95bef5..1f52868 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -503,6 +503,9 @@
inline void
Name::wireDecode(const Block &wire)
{
+ if (wire.type() != Tlv::Name)
+ throw Tlv::Error("Unexpected TLV type when decoding Name");
+
m_nameBlock = wire;
m_nameBlock.parse();
}
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index ca732d8..d9d475d 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -223,14 +223,14 @@
SignatureSha256WithRsa signature;
signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
- Name& interestName = interest.getName().append(signature.getInfo());
+ Name signedName = Name(interest.getName()).append(signature.getInfo());
- signature.setValue(Tpm::signInTpm(interestName.wireEncode().value(),
- interestName.wireEncode().value_size(),
+ signature.setValue(Tpm::signInTpm(signedName.wireEncode().value(),
+ signedName.wireEncode().value_size(),
cert->getPublicKeyName(),
DIGEST_ALGORITHM_SHA256));
-
- interest.getName().append(signature.getValue());
+ signedName.append(signature.getValue());
+ interest.setName(signedName);
}
/**
@@ -402,14 +402,15 @@
SignatureSha256WithRsa signature;
signature.setKeyLocator(certificate.getName().getPrefix(-1)); // implicit conversion should take care
- Name& interestName = interest.getName().append(signature.getInfo());
+ Name signedName = Name(interest.getName()).append(signature.getInfo());
- signature.setValue(Tpm::signInTpm(interestName.wireEncode().value(),
- interestName.wireEncode().value_size(),
+ signature.setValue(Tpm::signInTpm(signedName.wireEncode().value(),
+ signedName.wireEncode().value_size(),
certificate.getPublicKeyName(),
DIGEST_ALGORITHM_SHA256));
- interestName.append(signature.getValue());
+ signedName.append(signature.getValue());
+ interest.setName(signedName);
}
/**
diff --git a/src/security/signature-sha256-with-rsa.hpp b/src/security/signature-sha256-with-rsa.hpp
index cfcef90..b1dd6e1 100644
--- a/src/security/signature-sha256-with-rsa.hpp
+++ b/src/security/signature-sha256-with-rsa.hpp
@@ -9,6 +9,7 @@
#define NDN_SIGNATURE_SHA256_WITH_RSA_HPP
#include "../data.hpp"
+#include "../encoding/tlv.hpp"
namespace ndn {
diff --git a/src/selectors.hpp b/src/selectors.hpp
new file mode 100644
index 0000000..19a996b
--- /dev/null
+++ b/src/selectors.hpp
@@ -0,0 +1,294 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SELECTORS_HPP
+#define NDN_SELECTORS_HPP
+
+#include "common.hpp"
+#include "exclude.hpp"
+#include "encoding/encoding-buffer.hpp"
+
+namespace ndn {
+
+/**
+ * @brief Abstraction implementing Interest selectors
+ */
+class Selectors
+{
+public:
+ Selectors()
+ : m_minSuffixComponents(-1)
+ , m_maxSuffixComponents(-1)
+ , m_childSelector(-1)
+ , m_mustBeFresh(false)
+ {
+ }
+
+ Selectors(int minSuffixComponents, int maxSuffixComponents,
+ const Exclude& exclude,
+ int childSelector,
+ bool mustBeFresh)
+ : m_minSuffixComponents(minSuffixComponents)
+ , m_maxSuffixComponents(maxSuffixComponents)
+ , m_exclude(exclude)
+ , m_childSelector(childSelector)
+ , m_mustBeFresh(mustBeFresh)
+ {
+ }
+
+ Selectors(const Block& wire)
+ {
+ wireDecode(wire);
+ }
+
+ bool
+ empty() const;
+
+ /**
+ * @brief Fast encoding or block size estimation
+ */
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T> &block) const;
+
+ /**
+ * @brief Encode to a wire format
+ */
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode the input from wire format
+ */
+ void
+ wireDecode(const Block &wire);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int
+ getMinSuffixComponents() const
+ {
+ return m_minSuffixComponents;
+ }
+
+ Selectors&
+ setMinSuffixComponents(int minSuffixComponents)
+ {
+ m_minSuffixComponents = minSuffixComponents;
+ wire_.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getMaxSuffixComponents() const
+ {
+ return m_maxSuffixComponents;
+ }
+
+ Selectors&
+ setMaxSuffixComponents(int maxSuffixComponents)
+ {
+ m_maxSuffixComponents = maxSuffixComponents;
+ wire_.reset();
+ return *this;
+ }
+
+ //
+
+ const Exclude&
+ getExclude() const
+ {
+ return m_exclude;
+ }
+
+ Selectors&
+ setExclude(const Exclude& exclude)
+ {
+ m_exclude = exclude;
+ wire_.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getChildSelector() const
+ {
+ return m_childSelector;
+ }
+
+ Selectors&
+ setChildSelector(int childSelector)
+ {
+ m_childSelector = childSelector;
+ wire_.reset();
+ return *this;
+ }
+
+ //
+
+ int
+ getMustBeFresh() const
+ {
+ return m_mustBeFresh;
+ }
+
+ Selectors&
+ setMustBeFresh(bool mustBeFresh)
+ {
+ m_mustBeFresh = mustBeFresh;
+ wire_.reset();
+ return *this;
+ }
+
+private:
+ int m_minSuffixComponents;
+ int m_maxSuffixComponents;
+ Exclude m_exclude;
+ int m_childSelector;
+ bool m_mustBeFresh;
+
+ mutable Block wire_;
+};
+
+inline bool
+Selectors::empty() const
+{
+ return
+ (m_minSuffixComponents < 0 &&
+ m_maxSuffixComponents < 0 &&
+ m_exclude.empty() &&
+ m_childSelector < 0 &&
+ !m_mustBeFresh);
+}
+
+template<bool T>
+inline size_t
+Selectors::wireEncode(EncodingImpl<T> &block) const
+{
+ size_t total_len = 0;
+
+ // Selectors ::= SELECTORS-TYPE TLV-LENGTH
+ // MinSuffixComponents?
+ // MaxSuffixComponents?
+ // PublisherPublicKeyLocator?
+ // Exclude?
+ // ChildSelector?
+ // MustBeFresh?
+
+ // (reverse encoding)
+
+ // MustBeFresh
+ if (getMustBeFresh())
+ {
+ total_len += prependBooleanBlock(block, Tlv::MustBeFresh);
+ }
+
+ // ChildSelector
+ if (getChildSelector() >= 0)
+ {
+ total_len += prependNonNegativeIntegerBlock(block, Tlv::ChildSelector, getChildSelector());
+ }
+
+ // Exclude
+ if (!getExclude().empty())
+ {
+ total_len += getExclude().wireEncode(block);
+ }
+
+ // PublisherPublicKeyLocator
+ /// @todo Implement PublisherPublicKeyLocator selector
+
+ // MaxSuffixComponents
+ if (getMaxSuffixComponents() >= 0)
+ {
+ total_len += prependNonNegativeIntegerBlock(block, Tlv::MaxSuffixComponents,
+ getMaxSuffixComponents());
+ }
+
+ // MinSuffixComponents
+ if (getMinSuffixComponents() >= 0)
+ {
+ total_len += prependNonNegativeIntegerBlock(block, Tlv::MinSuffixComponents,
+ getMinSuffixComponents());
+ }
+
+ total_len += block.prependVarNumber(total_len);
+ total_len += block.prependVarNumber(Tlv::Selectors);
+ return total_len;
+}
+
+inline const Block &
+Selectors::wireEncode() const
+{
+ if (wire_.hasWire())
+ return wire_;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ wire_ = buffer.block();
+ return wire_;
+}
+
+inline void
+Selectors::wireDecode(const Block &wire)
+{
+ if (wire.type() != Tlv::Selectors)
+ throw Tlv::Error("Unexpected TLV type when decoding Selectors");
+
+ *this = Selectors();
+
+ wire_ = wire;
+ wire_.parse();
+
+ // MinSuffixComponents
+ Block::element_const_iterator val = wire_.find(Tlv::MinSuffixComponents);
+ if (val != wire_.elements_end())
+ {
+ m_minSuffixComponents = readNonNegativeInteger(*val);
+ }
+
+ // MaxSuffixComponents
+ val = wire_.find(Tlv::MaxSuffixComponents);
+ if (val != wire_.elements_end())
+ {
+ m_maxSuffixComponents = readNonNegativeInteger(*val);
+ }
+
+ // Exclude
+ val = wire_.find(Tlv::Exclude);
+ if (val != wire_.elements_end())
+ {
+ m_exclude.wireDecode(*val);
+ }
+
+ // ChildSelector
+ val = wire_.find(Tlv::ChildSelector);
+ if (val != wire_.elements_end())
+ {
+ m_childSelector = readNonNegativeInteger(*val);
+ }
+
+ //MustBeFresh aka AnswerOriginKind
+ val = wire_.find(Tlv::MustBeFresh);
+ if (val != wire_.elements_end())
+ {
+ m_mustBeFresh = true;
+ }
+}
+
+} // namespace ndn
+
+#endif // NDN_SELECTORS_HPP
diff --git a/tests/test-command-interest.cpp b/tests/test-command-interest.cpp
index 59619ca..fb447d9 100644
--- a/tests/test-command-interest.cpp
+++ b/tests/test-command-interest.cpp
@@ -63,7 +63,12 @@
shared_ptr<Interest> commandInterest2 = make_shared<Interest>("/TestCommandInterest/Validation/Command2");
int64_t timestamp = time::now() / 1000000;
timestamp -= 5000;
- commandInterest2->getName().append(name::Component::fromNumber(timestamp)).append(name::Component::fromNumber(random::generateWord64()));
+ Name commandName = commandInterest2->getName();
+ commandName
+ .append(name::Component::fromNumber(timestamp))
+ .append(name::Component::fromNumber(random::generateWord64()));
+ commandInterest2->setName(commandName);
+
keyChain.signByIdentity(*commandInterest2, identity);
validator.validate(*commandInterest2,
bind(&TestCore::validated, &core, _1),
diff --git a/tests/test-interest.cpp b/tests/test-interest.cpp
index 2c8f772..df0cdf3 100644
--- a/tests/test-interest.cpp
+++ b/tests/test-interest.cpp
@@ -89,9 +89,11 @@
i.setMaxSuffixComponents(1);
i.setChildSelector(1);
i.setMustBeFresh(false);
- i.getExclude()
+ Exclude exclude;
+ exclude
.excludeOne(name::Component("alex"))
.excludeRange(name::Component("xxxx"), name::Component("yyyy"));
+ i.setExclude(exclude);
i.setNonce(1);
const Block &wire = i.wireEncode();