diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp index 67b8f52b..55a9062f 100644 --- a/daemon/fw/forwarder.cpp +++ b/daemon/fw/forwarder.cpp @@ -574,7 +574,7 @@ void Forwarder::setExpiryTimer(const shared_ptr& pitEntry, time::milliseconds duration) { BOOST_ASSERT(pitEntry); - BOOST_ASSERT(duration >= 0_ms); + duration = std::max(duration, 0_ms); pitEntry->expiryTimer.cancel(); pitEntry->expiryTimer = getScheduler().schedule(duration, [=] { onInterestFinalize(pitEntry); }); diff --git a/daemon/table/pit-face-record.cpp b/daemon/table/pit-face-record.cpp index d58ec96d..639f4248 100644 --- a/daemon/table/pit-face-record.cpp +++ b/daemon/table/pit-face-record.cpp @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2014-2019, Regents of the University of California, + * Copyright (c) 2014-2020, Regents of the University of California, * Arizona Board of Regents, * Colorado State University, * University Pierre & Marie Curie, Sorbonne University, @@ -28,6 +28,9 @@ namespace nfd { namespace pit { +// Impose a maximum lifetime to prevent integer overflow when calculating m_expiry. +static const time::milliseconds MAX_LIFETIME{10_days}; + void FaceRecord::update(const Interest& interest) { @@ -35,9 +38,7 @@ FaceRecord::update(const Interest& interest) m_lastRenewed = time::steady_clock::now(); auto lifetime = interest.getInterestLifetime(); - if (lifetime < 0_ms) { - lifetime = ndn::DEFAULT_INTEREST_LIFETIME; - } + lifetime = std::min(lifetime, MAX_LIFETIME); m_expiry = m_lastRenewed + lifetime; } diff --git a/tests/daemon/table/pit-entry.t.cpp b/tests/daemon/table/pit-entry.t.cpp index 8bdb5fea..00993ee5 100644 --- a/tests/daemon/table/pit-entry.t.cpp +++ b/tests/daemon/table/pit-entry.t.cpp @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2014-2019, Regents of the University of California, + * Copyright (c) 2014-2020, Regents of the University of California, * Arizona Board of Regents, * Colorado State University, * University Pierre & Marie Curie, Sorbonne University, @@ -29,6 +29,10 @@ #include "tests/daemon/global-io-fixture.hpp" #include "tests/daemon/face/dummy-face.hpp" +#include + +namespace bdata = boost::unit_test::data; + namespace nfd { namespace pit { namespace tests { @@ -166,17 +170,42 @@ BOOST_AUTO_TEST_CASE(InOutRecords) BOOST_CHECK(entry.getOutRecord(*face2) == entry.out_end()); } -BOOST_AUTO_TEST_CASE(Lifetime) +const time::milliseconds lifetimes[] = { + -1_ms, // unset + 1_ms, + ndn::DEFAULT_INTEREST_LIFETIME, + 8624_ms, + 86400_s, + time::milliseconds(std::numeric_limits::max()), +}; + +BOOST_DATA_TEST_CASE(Lifetime, bdata::make(lifetimes), lifetime) { auto interest = makeInterest("/7oIEurbgy6"); + if (lifetime >= 0_ms) { + interest->setInterestLifetime(lifetime); + } + + auto expectedLifetime = lifetime; + if (lifetime < 0_ms) { + expectedLifetime = ndn::DEFAULT_INTEREST_LIFETIME; + } + else if (lifetime > 10_days) { + expectedLifetime = 10_days; + } + auto face = make_shared(); Entry entry(*interest); auto inIt = entry.insertOrUpdateInRecord(*face, *interest); - BOOST_CHECK_GT(inIt->getExpiry(), time::steady_clock::now()); + auto expiryFromNow = inIt->getExpiry() - time::steady_clock::now(); + BOOST_CHECK_GT(expiryFromNow, 0_ms); + BOOST_CHECK_LT(time::abs(expiryFromNow - expectedLifetime), 100_ms); auto outIt = entry.insertOrUpdateOutRecord(*face, *interest); - BOOST_CHECK_GT(outIt->getExpiry(), time::steady_clock::now()); + expiryFromNow = outIt->getExpiry() - time::steady_clock::now(); + BOOST_CHECK_GT(expiryFromNow, 0_ms); + BOOST_CHECK_LT(time::abs(expiryFromNow - expectedLifetime), 100_ms); } BOOST_AUTO_TEST_CASE(OutRecordNack)