diff --git a/ndn-cxx/data.hpp b/ndn-cxx/data.hpp index b4f8179f..043d7021 100644 --- a/ndn-cxx/data.hpp +++ b/ndn-cxx/data.hpp @@ -44,19 +44,23 @@ class Data : public PacketBase, public std::enable_shared_from_this using tlv::Error::Error; }; - /** @brief Construct an unsigned Data packet with given @p name and empty Content. - * @warning In certain contexts that use `Data::shared_from_this()`, Data must be created using - * `std::make_shared`. Otherwise, `shared_from_this()` may trigger undefined behavior. - * One example where this is necessary is storing Data into a subclass of InMemoryStorage. + /** + * @brief Construct an unsigned Data packet with given @p name and empty Content. + * + * @warning In certain contexts that use `Data::shared_from_this()`, the Data must be created + * using `std::make_shared`. Otherwise, `shared_from_this()` will throw `std::bad_weak_ptr`. + * One example where this is necessary is storing Data into a subclass of InMemoryStorage. */ explicit Data(const Name& name = Name()); - /** @brief Construct a Data packet by decoding from @p wire. - * @param wire TLV element of type tlv::Data; may be signed or unsigned. - * @warning In certain contexts that use `Data::shared_from_this()`, Data must be created using - * `std::make_shared`. Otherwise, `shared_from_this()` may trigger undefined behavior. - * One example where this is necessary is storing Data into a subclass of InMemoryStorage. + /** + * @brief Construct a Data packet by decoding from @p wire. + * @param wire TLV element of type tlv::Data; may be signed or unsigned. + * + * @warning In certain contexts that use `Data::shared_from_this()`, the Data must be created + * using `std::make_shared`. Otherwise, `shared_from_this()` will throw `std::bad_weak_ptr`. + * One example where this is necessary is storing Data into a subclass of InMemoryStorage. */ explicit Data(const Block& wire); @@ -301,37 +305,54 @@ class Data : public PacketBase, public std::enable_shared_from_this extractSignedRanges() const; public: // MetaInfo fields + /** + * @copydoc MetaInfo::getType() + */ uint32_t - getContentType() const + getContentType() const noexcept { return m_metaInfo.getType(); } + /** + * @copydoc MetaInfo::setType() + */ Data& setContentType(uint32_t type); + /** + * @copydoc MetaInfo::getFreshnessPeriod() + */ time::milliseconds - getFreshnessPeriod() const + getFreshnessPeriod() const noexcept { return m_metaInfo.getFreshnessPeriod(); } + /** + * @copydoc MetaInfo::setFreshnessPeriod() + */ Data& setFreshnessPeriod(time::milliseconds freshnessPeriod); + /** + * @copydoc MetaInfo::getFinalBlock() + */ const std::optional& - getFinalBlock() const + getFinalBlock() const noexcept { return m_metaInfo.getFinalBlock(); } + /** + * @copydoc MetaInfo::setFinalBlock() + */ Data& setFinalBlock(std::optional finalBlockId); public: // SignatureInfo fields /** - * @brief Get the `SignatureType`. - * @return tlv::SignatureTypeValue, or -1 to indicate the signature is invalid. + * @copydoc SignatureInfo::getSignatureType() */ int32_t getSignatureType() const noexcept diff --git a/ndn-cxx/interest.cpp b/ndn-cxx/interest.cpp index 4dfde5cb..8a07cc8f 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-2023 Regents of the University of California. + * Copyright (c) 2013-2024 Regents of the University of California. * * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). * @@ -82,14 +82,13 @@ Interest::wireEncode(EncodingImpl& encoder) const } // HopLimit - if (getHopLimit()) { + if (m_hopLimit) { totalLength += prependBinaryBlock(encoder, tlv::HopLimit, {*m_hopLimit}); } // InterestLifetime - if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) { - totalLength += prependNonNegativeIntegerBlock(encoder, tlv::InterestLifetime, - static_cast(getInterestLifetime().count())); + if (m_interestLifetime != DEFAULT_INTEREST_LIFETIME.count()) { + totalLength += prependNonNegativeIntegerBlock(encoder, tlv::InterestLifetime, m_interestLifetime); } // Nonce @@ -177,7 +176,7 @@ Interest::wireDecode(const Block& wire) m_canBePrefix = m_mustBeFresh = false; m_forwardingHint.clear(); m_nonce.reset(); - m_interestLifetime = DEFAULT_INTEREST_LIFETIME; + m_interestLifetime = DEFAULT_INTEREST_LIFETIME.count(); m_hopLimit.reset(); m_parameters.clear(); @@ -262,7 +261,7 @@ Interest::wireDecode(const Block& wire) if (lastElement >= 6) { NDN_THROW(Error("InterestLifetime element is out of order")); } - m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element)); + m_interestLifetime = readNonNegativeInteger(*element); lastElement = 6; break; } @@ -439,6 +438,15 @@ Interest::refreshNonce() m_wire.reset(); } +time::milliseconds +Interest::getInterestLifetime() const noexcept +{ + if (m_interestLifetime > static_cast(time::milliseconds::max().count())) { + return time::milliseconds::max(); + } + return time::milliseconds(m_interestLifetime); +} + Interest& Interest::setInterestLifetime(time::milliseconds lifetime) { @@ -446,8 +454,9 @@ Interest::setInterestLifetime(time::milliseconds lifetime) NDN_THROW(std::invalid_argument("InterestLifetime must be >= 0")); } - if (lifetime != m_interestLifetime) { - m_interestLifetime = lifetime; + uint64_t lifetimeMillis = static_cast(lifetime.count()); + if (lifetimeMillis != m_interestLifetime) { + m_interestLifetime = lifetimeMillis; m_wire.reset(); } return *this; diff --git a/ndn-cxx/interest.hpp b/ndn-cxx/interest.hpp index 965da326..86b7d956 100644 --- a/ndn-cxx/interest.hpp +++ b/ndn-cxx/interest.hpp @@ -94,40 +94,46 @@ class Interest : public PacketBase, public std::enable_shared_from_this size_t wireEncode(EncodingImpl& encoder) const; - /** @brief Encode into a Block. + /** + * @brief Encode into a Block. */ const Block& wireEncode() const; - /** @brief Decode from @p wire. + /** + * @brief Decode from @p wire. */ void wireDecode(const Block& wire); - /** @brief Check if this instance has cached wire encoding. + /** + * @brief Check if this instance has cached wire encoding. */ bool hasWire() const noexcept @@ -135,12 +141,14 @@ class Interest : public PacketBase, public std::enable_shared_from_this m_forwardingHint; mutable std::optional m_nonce; - time::milliseconds m_interestLifetime = DEFAULT_INTEREST_LIFETIME; + uint64_t m_interestLifetime = DEFAULT_INTEREST_LIFETIME.count(); std::optional m_hopLimit; bool m_canBePrefix = false; bool m_mustBeFresh = false; diff --git a/ndn-cxx/meta-info.cpp b/ndn-cxx/meta-info.cpp index 3e4d6f12..918b089f 100644 --- a/ndn-cxx/meta-info.cpp +++ b/ndn-cxx/meta-info.cpp @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2013-2023 Regents of the University of California. + * Copyright (c) 2013-2024 Regents of the University of California. * * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). * @@ -43,7 +43,7 @@ MetaInfo::setType(uint32_t type) } time::milliseconds -MetaInfo::getFreshnessPeriod() const +MetaInfo::getFreshnessPeriod() const noexcept { if (m_freshnessPeriod > static_cast(time::milliseconds::max().count())) { return time::milliseconds::max(); @@ -144,7 +144,7 @@ MetaInfo::wireEncode(EncodingImpl& encoder) const } // FreshnessPeriod - if (m_freshnessPeriod != static_cast(DEFAULT_FRESHNESS_PERIOD.count())) { + if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD.count()) { totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod, m_freshnessPeriod); } @@ -205,7 +205,7 @@ MetaInfo::wireDecode(const Block& wire) ++val; } else { - m_freshnessPeriod = static_cast(DEFAULT_FRESHNESS_PERIOD.count()); + m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD.count(); } // FinalBlockId diff --git a/ndn-cxx/meta-info.hpp b/ndn-cxx/meta-info.hpp index 5f0df928..52a8f08d 100644 --- a/ndn-cxx/meta-info.hpp +++ b/ndn-cxx/meta-info.hpp @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2013-2023 Regents of the University of California. + * Copyright (c) 2013-2024 Regents of the University of California. * * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). * @@ -86,18 +86,20 @@ class MetaInfo wireDecode(const Block& wire); public: // getter/setter - /** @brief Return the value of `ContentType`. + /** + * @brief Return the value of `ContentType`. * - * If the `ContentType` element is not present, returns tlv::ContentType_Blob. + * If the `ContentType` element is not present, returns tlv::ContentType_Blob. */ uint32_t - getType() const + getType() const noexcept { return m_type; } - /** @brief Set `ContentType`. - * @param type a number defined in tlv::ContentTypeValue + /** + * @brief Set the `ContentType`. + * @param type A number defined in tlv::ContentTypeValue */ MetaInfo& setType(uint32_t type); @@ -110,10 +112,11 @@ class MetaInfo * the nearest representable value. */ time::milliseconds - getFreshnessPeriod() const; + getFreshnessPeriod() const noexcept; - /** @brief Set `FreshnessPeriod`. - * @throw std::invalid_argument specified FreshnessPeriod is negative + /** + * @brief Set the `FreshnessPeriod`. + * @throw std::invalid_argument specified FreshnessPeriod is negative. */ MetaInfo& setFreshnessPeriod(time::milliseconds freshnessPeriod); @@ -122,13 +125,13 @@ class MetaInfo * @brief Return the value of `FinalBlockId`. */ const std::optional& - getFinalBlock() const + getFinalBlock() const noexcept { return m_finalBlockId; } /** - * @brief Set `FinalBlockId`. + * @brief Set the `FinalBlockId`. */ MetaInfo& setFinalBlock(std::optional finalBlockId); @@ -196,7 +199,7 @@ class MetaInfo private: uint32_t m_type = tlv::ContentType_Blob; - uint64_t m_freshnessPeriod = static_cast(DEFAULT_FRESHNESS_PERIOD.count()); + uint64_t m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD.count(); std::optional m_finalBlockId; std::list m_appMetaInfo; diff --git a/tests/unit/interest.t.cpp b/tests/unit/interest.t.cpp index 4c540b78..5e64fb1d 100644 --- a/tests/unit/interest.t.cpp +++ b/tests/unit/interest.t.cpp @@ -611,6 +611,23 @@ BOOST_AUTO_TEST_CASE(BadNonce) [] (const auto& e) { return e.what() == "Nonce element is malformed"sv; }); } +BOOST_AUTO_TEST_CASE(LargeLifetime, + * ut::description("test for bug #4997")) +{ + i.wireDecode("050F 0703(080149) 0C087FFFFFFFFFFFFFFF"_block); + BOOST_CHECK_EQUAL(i.getInterestLifetime(), 0x7FFFFFFFFFFFFFFF_ms); + + i.wireDecode("050F 0703(080149) 0C088000000000000000"_block); + BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds::max()); + + i.wireDecode("050F 0703(080149) 0C08FFFFFFFFFFFFFFFF"_block); + BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds::max()); + + // force re-encoding + i.setNonce(0x957c6554); + BOOST_CHECK_EQUAL(i.wireEncode(), "0515 0703(080149) 0A04957C6554 0C08FFFFFFFFFFFFFFFF"_block); +} + BOOST_AUTO_TEST_CASE(BadHopLimit) { BOOST_CHECK_EXCEPTION(i.wireDecode("0507 0703080149 2200"_block), tlv::Error, diff --git a/tests/unit/meta-info.t.cpp b/tests/unit/meta-info.t.cpp index f375607e..b9bb0df4 100644 --- a/tests/unit/meta-info.t.cpp +++ b/tests/unit/meta-info.t.cpp @@ -78,9 +78,9 @@ BOOST_AUTO_TEST_CASE(EncodeDecode) BOOST_CHECK_EQUAL(b.wireEncode(), wire3); } -BOOST_AUTO_TEST_CASE(FreshnessPeriodOverflow) +BOOST_AUTO_TEST_CASE(FreshnessPeriodOverflow, + * ut::description("test for bug #4997")) { - // Bug #4997 MetaInfo mi0("140A 19087FFFFFFFFFFFFFFF"_block); BOOST_CHECK_EQUAL(mi0.getFreshnessPeriod(), 0x7FFFFFFFFFFFFFFF_ms); @@ -89,6 +89,10 @@ BOOST_AUTO_TEST_CASE(FreshnessPeriodOverflow) MetaInfo mi2("140A 1908FFFFFFFFFFFFFFFF"_block); BOOST_CHECK_EQUAL(mi2.getFreshnessPeriod(), time::milliseconds::max()); + + // force re-encoding + mi2.setType(tlv::ContentType_Key); + BOOST_CHECK_EQUAL(mi2.wireEncode(), "140D 180102 1908FFFFFFFFFFFFFFFF"_block); } BOOST_AUTO_TEST_CASE(AppMetaInfo)