interest: Correcting encoding/decoding of Nonce field
Nonce field is now encoded as 4-byte uint8_t value, as defined by
NDN-TLV spec. In addition to that, setNonce will not reset
wireEncoding, rather than just modify the existing wire encoding, if it
is already exists.
Change-Id: Ibec3737ccfba70fec5c0531487782a46fbc5600a
Refs: #1600
diff --git a/src/encoding/encoding-buffer.hpp b/src/encoding/encoding-buffer.hpp
index b3f8916..d3fa3ac 100644
--- a/src/encoding/encoding-buffer.hpp
+++ b/src/encoding/encoding-buffer.hpp
@@ -131,6 +131,9 @@
prependVarNumber(uint64_t varNumber);
inline size_t
+ prependBlock(const Block& block);
+
+ inline size_t
appendByte(uint8_t value);
inline size_t
@@ -191,6 +194,9 @@
prependVarNumber(uint64_t varNumber);
inline size_t
+ prependBlock(const Block& block);
+
+ inline size_t
appendByte(uint8_t value);
inline size_t
@@ -203,6 +209,66 @@
appendVarNumber(uint64_t varNumber);
};
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+/// helper methods
+
+template<bool P>
+inline size_t
+prependNonNegativeIntegerBlock(EncodingImpl<P>& encoder, uint32_t type, uint64_t number)
+{
+ size_t valueLength = encoder.prependNonNegativeInteger(number);
+ size_t totalLength = valueLength;
+ totalLength += encoder.prependVarNumber(valueLength);
+ totalLength += encoder.prependVarNumber(type);
+
+ return totalLength;
+}
+
+template<bool P>
+inline size_t
+prependByteArrayBlock(EncodingImpl<P>& encoder, uint32_t type,
+ const uint8_t* array, size_t arraySize)
+{
+ size_t valueLength = encoder.prependByteArray(array, arraySize);
+ size_t totalLength = valueLength;
+ totalLength += encoder.prependVarNumber(valueLength);
+ totalLength += encoder.prependVarNumber(type);
+
+ return totalLength;
+}
+
+template<bool P>
+inline size_t
+prependBooleanBlock(EncodingImpl<P>& encoder, uint32_t type)
+{
+ size_t totalLength = encoder.prependVarNumber(0);
+ totalLength += encoder.prependVarNumber(type);
+
+ return totalLength;
+}
+
+
+template<bool P, class U>
+inline size_t
+prependNestedBlock(EncodingImpl<P>& encoder, uint32_t type, const U& nestedBlock)
+{
+ size_t valueLength = nestedBlock.wireEncode(encoder);
+ size_t totalLength = valueLength;
+ totalLength += encoder.prependVarNumber(valueLength);
+ totalLength += encoder.prependVarNumber(type);
+
+ return totalLength;
+}
+
+template<bool P>
+inline size_t
+prependBlock(EncodingImpl<P>& encoder, const Block& block)
+{
+ return encoder.prependByteArray(block.wire(), block.size());
+}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -415,6 +481,28 @@
}
}
+inline size_t
+EncodingImpl<encoding::Buffer>::prependBlock(const Block& block)
+{
+ if (block.hasWire()) {
+ return prependByteArray(block.wire(), block.size());
+ }
+ else {
+ return prependByteArrayBlock(*this, block.type(), block.value(), block.value_size());
+ }
+}
+
+inline size_t
+EncodingImpl<encoding::Estimator>::prependBlock(const Block& block)
+{
+ if (block.hasWire()) {
+ return block.size();
+ }
+ else {
+ return prependByteArrayBlock(*this, block.type(), block.value(), block.value_size());
+ }
+}
+
/////////////////////////////////////////////////////////
// Append to the back of the buffer. Resize if needed. //
/////////////////////////////////////////////////////////
@@ -512,64 +600,6 @@
return prependVarNumber(varNumber);
}
-/// helper methods
-
-template<bool P>
-inline size_t
-prependNonNegativeIntegerBlock(EncodingImpl<P>& encoder, uint32_t type, uint64_t number)
-{
- size_t valueLength = encoder.prependNonNegativeInteger(number);
- size_t totalLength = valueLength;
- totalLength += encoder.prependVarNumber(valueLength);
- totalLength += encoder.prependVarNumber(type);
-
- return totalLength;
-}
-
-template<bool P>
-inline size_t
-prependByteArrayBlock(EncodingImpl<P>& encoder, uint32_t type,
- const uint8_t* array, size_t arraySize)
-{
- size_t valueLength = encoder.prependByteArray(array, arraySize);
- size_t totalLength = valueLength;
- totalLength += encoder.prependVarNumber(valueLength);
- totalLength += encoder.prependVarNumber(type);
-
- return totalLength;
-}
-
-template<bool P>
-inline size_t
-prependBooleanBlock(EncodingImpl<P>& encoder, uint32_t type)
-{
- size_t totalLength = encoder.prependVarNumber(0);
- totalLength += encoder.prependVarNumber(type);
-
- return totalLength;
-}
-
-
-template<bool P, class U>
-inline size_t
-prependNestedBlock(EncodingImpl<P>& encoder, uint32_t type, const U& nestedBlock)
-{
- size_t valueLength = nestedBlock.wireEncode(encoder);
- size_t totalLength = valueLength;
- totalLength += encoder.prependVarNumber(valueLength);
- totalLength += encoder.prependVarNumber(type);
-
- return totalLength;
-}
-
-template<bool P>
-inline size_t
-prependBlock(EncodingImpl<P>& encoder, const Block& block)
-{
- return encoder.prependByteArray(block.wire(), block.size());
-}
-
-
} // ndn
#endif // NDN_ENCODING_ENCODING_BUFFER_HPP
diff --git a/src/interest.cpp b/src/interest.cpp
index cd3271e..9e5b129 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -29,15 +29,34 @@
namespace ndn {
-const uint32_t&
+uint32_t
Interest::getNonce() const
{
- if (m_nonce == 0)
- m_nonce = random::generateWord32();
+ if (!m_nonce.hasWire())
+ const_cast<Interest*>(this)->setNonce(random::generateWord32());
- return m_nonce;
+ if (m_nonce.value_size() == sizeof(uint32_t))
+ return *reinterpret_cast<const uint32_t*>(m_nonce.value());
+ else {
+ // for compatibility reasons. Should be removed eventually
+ return readNonNegativeInteger(m_nonce);
+ }
}
+Interest&
+Interest::setNonce(uint32_t nonce)
+{
+ if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
+ std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
+ }
+ else {
+ m_nonce = dataBlock(Tlv::Nonce,
+ reinterpret_cast<const uint8_t*>(&nonce),
+ sizeof(nonce));
+ m_wire.reset();
+ }
+ return *this;
+}
bool
Interest::matchesName(const Name& name) const
@@ -122,7 +141,7 @@
delim = '&';
}
- if (interest.getNonce() > 0) {
+ if (interest.hasNonce()) {
os << delim << "ndn.Nonce=" << interest.getNonce();
delim = '&';
}
diff --git a/src/interest.hpp b/src/interest.hpp
index d949950..138ea7c 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -54,8 +54,7 @@
* Otherwise, Interest::shared_from_this() will throw an exception.
*/
Interest()
- : m_nonce(0)
- , m_scope(-1)
+ : m_scope(-1)
, m_interestLifetime(time::milliseconds::min())
{
}
@@ -74,7 +73,6 @@
*/
Interest(const Name& name)
: m_name(name)
- , m_nonce(0)
, m_scope(-1)
, m_interestLifetime(time::milliseconds::min())
{
@@ -95,7 +93,6 @@
*/
Interest(const Name& name, const time::milliseconds& interestLifetime)
: m_name(name)
- , m_nonce(0)
, m_scope(-1)
, m_interestLifetime(interestLifetime)
{
@@ -118,10 +115,12 @@
uint32_t nonce = 0)
: m_name(name)
, m_selectors(selectors)
- , m_nonce(nonce)
, m_scope(scope)
, m_interestLifetime(interestLifetime)
{
+ if (nonce > 0) {
+ setNonce(nonce);
+ }
}
/**
@@ -153,10 +152,12 @@
.setExclude(exclude)
.setChildSelector(childSelector)
.setMustBeFresh(mustBeFresh))
- , m_nonce(nonce)
, m_scope(scope)
, m_interestLifetime(interestLifetime)
{
+ if (nonce > 0) {
+ setNonce(nonce);
+ }
}
/**
@@ -312,17 +313,27 @@
*
* Const reference needed for C decoding
*/
- const uint32_t&
+ uint32_t
getNonce() const;
- Interest&
- setNonce(uint32_t nonce)
+ /**
+ * @brief Check if Nonce set
+ */
+ bool
+ hasNonce() const
{
- m_nonce = nonce;
- m_wire.reset();
- return *this;
+ return m_nonce.hasWire();
}
+ /**
+ * @brief Set Interest's nonce
+ *
+ * Note that if wire format already exists, this call simply replaces nonce in the
+ * existing wire format, without resetting and recreating it.
+ */
+ Interest&
+ setNonce(uint32_t nonce);
+
//
nfd::LocalControlHeader&
@@ -489,7 +500,7 @@
private:
Name m_name;
Selectors m_selectors;
- mutable uint32_t m_nonce;
+ mutable Block m_nonce;
int m_scope;
time::milliseconds m_interestLifetime;
@@ -547,7 +558,8 @@
}
// Nonce
- totalLength += prependNonNegativeIntegerBlock(block, Tlv::Nonce, getNonce());
+ getNonce(); // to ensure that Nonce is properly set
+ totalLength += block.prependBlock(m_nonce);
// Selectors
if (!getSelectors().empty())
@@ -558,8 +570,8 @@
// Name
totalLength += getName().wireEncode(block);
- totalLength += block.prependVarNumber (totalLength);
- totalLength += block.prependVarNumber (Tlv::Interest);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(Tlv::Interest);
return totalLength;
}
@@ -575,7 +587,9 @@
EncodingBuffer buffer(estimatedSize, 0);
wireEncode(buffer);
- m_wire = buffer.block();
+ // to ensure that Nonce block points to the right memory location
+ const_cast<Interest*>(this)->wireDecode(buffer.block());
+
return m_wire;
}
@@ -608,13 +622,7 @@
m_selectors = Selectors();
// Nonce
- val = m_wire.find(Tlv::Nonce);
- if (val != m_wire.elements_end())
- {
- m_nonce = readNonNegativeInteger(*val);
- }
- else
- m_nonce = 0;
+ m_nonce = m_wire.get(Tlv::Nonce);
// Scope
val = m_wire.find(Tlv::Scope);
diff --git a/tests/unit-tests/test-interest.cpp b/tests/unit-tests/test-interest.cpp
index 6e7c6b4..25f79fa 100644
--- a/tests/unit-tests/test-interest.cpp
+++ b/tests/unit-tests/test-interest.cpp
@@ -36,7 +36,7 @@
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Selectors>));
const uint8_t Interest1[] = {
- 0x05, 0x59, // NDN Interest
+ 0x05, 0x5c, // NDN Interest
0x07, 0x14, // Name
0x08, 0x5, // NameComponent
0x6c, 0x6f, 0x63, 0x61, 0x6c,
@@ -65,8 +65,46 @@
0x79, 0x79, 0x79, 0x79,
0x11, 0x1, // ChildSelector
0x1,
- 0x0a, 0x1, // Nonce
+ 0x0a, 0x4, // Nonce
+ 0x1, 0x0, 0x0, 0x00,
+ 0x0b, 0x1, // Scope
0x1,
+ 0x0c, // InterestLifetime
+ 0x2, 0x3, 0xe8
+};
+
+const uint8_t Interest2[] = {
+ 0x05, 0x5c, // NDN Interest
+ 0x07, 0x14, // Name
+ 0x08, 0x5, // NameComponent
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x08, 0x3, // NameComponent
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x6, // NameComponent
+ 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+ 0x09, 0x37, // Selectors
+ 0x0d, 0x1, 0x1, // MinSuffix
+ 0x0e, 0x1, 0x1, // MaxSuffix
+ 0x1c, 0x16, // KeyLocator
+ 0x07, 0x14, // Name
+ 0x08, 0x04,
+ 0x74, 0x65, 0x73, 0x74,
+ 0x08, 0x03,
+ 0x6b, 0x65, 0x79,
+ 0x08, 0x07,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
+ 0x10, 0x14, // Exclude
+ 0x08, 0x4, // NameComponent
+ 0x61, 0x6c, 0x65, 0x78,
+ 0x08, 0x4, // NameComponent
+ 0x78, 0x78, 0x78, 0x78,
+ 0x13, 0x0, // Any
+ 0x08, 0x4, // NameComponent
+ 0x79, 0x79, 0x79, 0x79,
+ 0x11, 0x1, // ChildSelector
+ 0x1,
+ 0x0a, 0x4, // Nonce
+ 0x2, 0x0, 0x0, 0x00,
0x0b, 0x1, // Scope
0x1,
0x0c, // InterestLifetime
@@ -74,15 +112,16 @@
};
const uint8_t InterestWithLocalControlHeader[] = {
- 0x50, 0x22, 0x51, 0x01, 0x0a, 0x05, 0x1d, 0x07, 0x14, 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61,
- 0x6c, 0x08, 0x03, 0x6e, 0x64, 0x6e, 0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x09,
- 0x02, 0x12, 0x00, 0x0a, 0x01, 0x01
+ 0x50, 0x25, 0x51, 0x01, 0x0a,
+ 0x05, 0x20, 0x07, 0x14, 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x08, 0x03, 0x6e, 0x64,
+ 0x6e, 0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x09, 0x02, 0x12, 0x00, 0x0a, 0x04,
+ 0x01, 0x00, 0x00, 0x00
};
const uint8_t InterestWithoutLocalControlHeader[] = {
- 0x05, 0x1d, 0x07, 0x14, 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x08, 0x03, 0x6e, 0x64,
- 0x6e, 0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x09, 0x02, 0x12, 0x00, 0x0a, 0x01,
- 0x01
+ 0x05, 0x20, 0x07, 0x14, 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x08, 0x03, 0x6e, 0x64,
+ 0x6e, 0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x09, 0x02, 0x12, 0x00, 0x0a, 0x04,
+ 0x01, 0x00, 0x00, 0x00
};
BOOST_AUTO_TEST_CASE(InterestEqualityChecks)
@@ -287,12 +326,22 @@
i.setExclude(exclude);
i.setNonce(1);
+ BOOST_CHECK_EQUAL(i.hasWire(), false);
const Block &wire = i.wireEncode();
+ BOOST_CHECK_EQUAL(i.hasWire(), true);
BOOST_CHECK_EQUAL_COLLECTIONS(Interest1, Interest1 + sizeof(Interest1),
wire.begin(), wire.end());
-}
+ const uint8_t* originalWire = wire.wire();
+ i.setNonce(2);
+ BOOST_CHECK_EQUAL(i.hasWire(), true);
+ BOOST_CHECK_EQUAL(originalWire, i.wireEncode().wire());
+ BOOST_CHECK_EQUAL(i.hasWire(), true);
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(Interest2, Interest2 + sizeof(Interest2),
+ wire.begin(), wire.end());
+}
BOOST_AUTO_TEST_CASE(EncodeWithLocalHeader)
{