face: move packet encoding to Impl class
Practical limit of packet size is now enforced on encoded NDNLPv2 packets instead of network-layer packets. If a packet exceeds size limit, the face throws a Face::OversizedPacketError exception. Since packet encoding may be asynchronous, this exception could be thrown by Face::processEvents instead of Face::expressInterest and Face::put. refs #4228 Change-Id: Ib68cf80b3b8967fdd0ba040bd8ee595a0eff740e
This commit is contained in:
1 parent
2ed9e07e2a
commit
b6e276f277
8 files changed
+211
-142
No files matched your search
+56
-22
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "../face.hpp"
|
||||
#include "container-with-on-empty-signal.hpp"
|
||||
#include "lp-field-tag.hpp"
|
||||
#include "pending-interest.hpp"
|
||||
#include "registered-prefix.hpp"
|
||||
#include "../lp/packet.hpp"
|
||||
@@ -53,15 +54,14 @@ NDN_LOG_INIT(ndn.Face);
|
||||
|
||||
namespace ndn {
|
||||
|
||||
/**
|
||||
* @brief implementation detail of Face
|
||||
/** @brief implementation detail of Face
|
||||
*/
|
||||
class Face::Impl : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef ContainerWithOnEmptySignal<shared_ptr<PendingInterest>> PendingInterestTable;
|
||||
typedef std::list<shared_ptr<InterestFilterRecord>> InterestFilterTable;
|
||||
typedef ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>> RegisteredPrefixTable;
|
||||
using PendingInterestTable = ContainerWithOnEmptySignal<shared_ptr<PendingInterest>>;
|
||||
using InterestFilterTable = std::list<shared_ptr<InterestFilterRecord>>;
|
||||
using RegisteredPrefixTable = ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>>;
|
||||
|
||||
explicit
|
||||
Impl(Face& face)
|
||||
@@ -94,22 +94,12 @@ public: // consumer
|
||||
interest, afterSatisfied, afterNacked, afterTimeout, ref(m_scheduler))).first;
|
||||
(*entry)->setDeleter([this, entry] { m_pendingInterestTable.erase(entry); });
|
||||
|
||||
lp::Packet packet;
|
||||
lp::Packet lpPacket;
|
||||
addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, *interest);
|
||||
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, *interest);
|
||||
|
||||
shared_ptr<lp::NextHopFaceIdTag> nextHopFaceIdTag = interest->getTag<lp::NextHopFaceIdTag>();
|
||||
if (nextHopFaceIdTag != nullptr) {
|
||||
packet.add<lp::NextHopFaceIdField>(*nextHopFaceIdTag);
|
||||
}
|
||||
|
||||
shared_ptr<lp::CongestionMarkTag> congestionMarkTag = interest->getTag<lp::CongestionMarkTag>();
|
||||
if (congestionMarkTag != nullptr) {
|
||||
packet.add<lp::CongestionMarkField>(*congestionMarkTag);
|
||||
}
|
||||
|
||||
packet.add<lp::FragmentField>(std::make_pair(interest->wireEncode().begin(),
|
||||
interest->wireEncode().end()));
|
||||
|
||||
m_face.m_transport->send(packet.wireEncode());
|
||||
m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest->wireEncode(),
|
||||
'I', interest->getName()));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -189,10 +179,30 @@ public: // producer
|
||||
}
|
||||
|
||||
void
|
||||
asyncSend(const Block& wire)
|
||||
asyncPutData(const Data& data)
|
||||
{
|
||||
this->ensureConnected(true);
|
||||
m_face.m_transport->send(wire);
|
||||
|
||||
lp::Packet lpPacket;
|
||||
addFieldFromTag<lp::CachePolicyField, lp::CachePolicyTag>(lpPacket, data);
|
||||
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, data);
|
||||
|
||||
m_face.m_transport->send(finishEncoding(std::move(lpPacket), data.wireEncode(),
|
||||
'D', data.getName()));
|
||||
}
|
||||
|
||||
void
|
||||
asyncPutNack(const lp::Nack& nack)
|
||||
{
|
||||
this->ensureConnected(true);
|
||||
|
||||
lp::Packet lpPacket;
|
||||
lpPacket.add<lp::NackField>(nack.getHeader());
|
||||
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, nack);
|
||||
|
||||
const Interest& interest = nack.getInterest();
|
||||
m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest.wireEncode(),
|
||||
'N', interest.getName()));
|
||||
}
|
||||
|
||||
public: // prefix registration
|
||||
@@ -314,6 +324,30 @@ public: // IO routine
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/** @brief Finish packet encoding
|
||||
* @param lpPacket NDNLP packet without FragmentField
|
||||
* @param wire wire encoding of Interest or Data
|
||||
* @param pktType packet type, 'I' for Interest, 'D' for Data, 'N' for Nack
|
||||
* @param name packet name
|
||||
* @return wire encoding of either NDNLP or bare network packet
|
||||
* @throw Face::OversizedPacketError wire encoding exceeds limit
|
||||
*/
|
||||
Block
|
||||
finishEncoding(lp::Packet&& lpPacket, Block wire, char pktType, const Name& name)
|
||||
{
|
||||
if (!lpPacket.empty()) {
|
||||
lpPacket.add<lp::FragmentField>(std::make_pair(wire.begin(), wire.end()));
|
||||
wire = lpPacket.wireEncode();
|
||||
}
|
||||
|
||||
if (wire.size() > MAX_NDN_PACKET_SIZE) {
|
||||
BOOST_THROW_EXCEPTION(Face::OversizedPacketError(pktType, name, wire.size()));
|
||||
}
|
||||
|
||||
return wire;
|
||||
}
|
||||
|
||||
private:
|
||||
Face& m_face;
|
||||
util::Scheduler m_scheduler;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2013-2017 Regents of the University of California.
|
||||
*
|
||||
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
|
||||
*
|
||||
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received copies of the GNU General Public License and GNU Lesser
|
||||
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
|
||||
*/
|
||||
|
||||
#ifndef NDN_DETAIL_LP_FIELD_TAG_HPP
|
||||
#define NDN_DETAIL_LP_FIELD_TAG_HPP
|
||||
|
||||
#include "../lp/packet.hpp"
|
||||
#include "../lp/tags.hpp"
|
||||
|
||||
namespace ndn {
|
||||
|
||||
template<typename Field, typename Tag, typename Packet>
|
||||
void
|
||||
addFieldFromTag(lp::Packet& lpPacket, const Packet& packet)
|
||||
{
|
||||
shared_ptr<Tag> tag = static_cast<const TagHost&>(packet).getTag<Tag>();
|
||||
if (tag != nullptr) {
|
||||
lpPacket.add<Field>(*tag);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ndn
|
||||
|
||||
#endif // NDN_DETAIL_LP_FIELD_TAG_HPP
|
||||
+35
-70
@@ -30,9 +30,9 @@
|
||||
|
||||
// NDN_LOG_INIT(ndn.Face) is declared in face-impl.hpp
|
||||
|
||||
// A callback scheduled through io.post and io.dispatch may be invoked after the face
|
||||
// is destructed. To prevent this situation, these macros captures Face::m_impl as weak_ptr,
|
||||
// and skips callback execution if the face has been destructed.
|
||||
// A callback scheduled through io.post and io.dispatch may be invoked after the face is destructed.
|
||||
// To prevent this situation, use these macros to capture Face::m_impl as weak_ptr and skip callback
|
||||
// execution if the face has been destructed.
|
||||
#define IO_CAPTURE_WEAK_IMPL(OP) \
|
||||
{ \
|
||||
weak_ptr<Impl> implWeak(m_impl); \
|
||||
@@ -46,53 +46,63 @@
|
||||
|
||||
namespace ndn {
|
||||
|
||||
Face::OversizedPacketError::OversizedPacketError(char pktType, const Name& name, size_t wireSize)
|
||||
: Error((pktType == 'I' ? "Interest " : pktType == 'D' ? "Data " : "Nack ") +
|
||||
name.toUri() + " encodes into " + to_string(wireSize) + " octets, "
|
||||
"exceeding the implementation limit of " + to_string(MAX_NDN_PACKET_SIZE) + " octets")
|
||||
, pktType(pktType)
|
||||
, name(name)
|
||||
, wireSize(wireSize)
|
||||
{
|
||||
}
|
||||
|
||||
Face::Face(shared_ptr<Transport> transport)
|
||||
: m_internalIoService(new boost::asio::io_service())
|
||||
: m_internalIoService(make_unique<boost::asio::io_service>())
|
||||
, m_ioService(*m_internalIoService)
|
||||
, m_internalKeyChain(new KeyChain())
|
||||
, m_internalKeyChain(make_unique<KeyChain>())
|
||||
, m_impl(make_shared<Impl>(*this))
|
||||
{
|
||||
construct(transport, *m_internalKeyChain);
|
||||
construct(std::move(transport), *m_internalKeyChain);
|
||||
}
|
||||
|
||||
Face::Face(boost::asio::io_service& ioService)
|
||||
: m_ioService(ioService)
|
||||
, m_internalKeyChain(new KeyChain())
|
||||
, m_internalKeyChain(make_unique<KeyChain>())
|
||||
, m_impl(make_shared<Impl>(*this))
|
||||
{
|
||||
construct(nullptr, *m_internalKeyChain);
|
||||
}
|
||||
|
||||
Face::Face(const std::string& host, const std::string& port)
|
||||
: m_internalIoService(new boost::asio::io_service())
|
||||
: m_internalIoService(make_unique<boost::asio::io_service>())
|
||||
, m_ioService(*m_internalIoService)
|
||||
, m_internalKeyChain(new KeyChain())
|
||||
, m_internalKeyChain(make_unique<KeyChain>())
|
||||
, m_impl(make_shared<Impl>(*this))
|
||||
{
|
||||
construct(make_shared<TcpTransport>(host, port), *m_internalKeyChain);
|
||||
}
|
||||
|
||||
Face::Face(shared_ptr<Transport> transport, KeyChain& keyChain)
|
||||
: m_internalIoService(new boost::asio::io_service())
|
||||
: m_internalIoService(make_unique<boost::asio::io_service>())
|
||||
, m_ioService(*m_internalIoService)
|
||||
, m_impl(make_shared<Impl>(*this))
|
||||
{
|
||||
construct(transport, keyChain);
|
||||
construct(std::move(transport), keyChain);
|
||||
}
|
||||
|
||||
Face::Face(shared_ptr<Transport> transport, boost::asio::io_service& ioService)
|
||||
: m_ioService(ioService)
|
||||
, m_internalKeyChain(new KeyChain())
|
||||
, m_internalKeyChain(make_unique<KeyChain>())
|
||||
, m_impl(make_shared<Impl>(*this))
|
||||
{
|
||||
construct(transport, *m_internalKeyChain);
|
||||
construct(std::move(transport), *m_internalKeyChain);
|
||||
}
|
||||
|
||||
Face::Face(shared_ptr<Transport> transport, boost::asio::io_service& ioService, KeyChain& keyChain)
|
||||
: m_ioService(ioService)
|
||||
, m_impl(make_shared<Impl>(*this))
|
||||
{
|
||||
construct(transport, keyChain);
|
||||
construct(std::move(transport), keyChain);
|
||||
}
|
||||
|
||||
shared_ptr<Transport>
|
||||
@@ -147,9 +157,9 @@ Face::construct(shared_ptr<Transport> transport, KeyChain& keyChain)
|
||||
transport = makeDefaultTransport();
|
||||
}
|
||||
BOOST_ASSERT(transport != nullptr);
|
||||
m_transport = transport;
|
||||
m_transport = std::move(transport);
|
||||
|
||||
m_nfdController.reset(new nfd::Controller(*this, keyChain));
|
||||
m_nfdController = make_unique<nfd::Controller>(*this, keyChain);
|
||||
|
||||
IO_CAPTURE_WEAK_IMPL(post) {
|
||||
impl->ensureConnected(false);
|
||||
@@ -170,20 +180,15 @@ Face::expressInterest(const Interest& interest,
|
||||
const NackCallback& afterNacked,
|
||||
const TimeoutCallback& afterTimeout)
|
||||
{
|
||||
shared_ptr<Interest> interestToExpress = make_shared<Interest>(interest);
|
||||
shared_ptr<Interest> interest2 = make_shared<Interest>(interest);
|
||||
interest2->getNonce();
|
||||
NDN_LOG_DEBUG("<I " << *interest2);
|
||||
|
||||
// Use `interestToExpress` to avoid wire format creation for the original Interest
|
||||
if (interestToExpress->wireEncode().size() > MAX_NDN_PACKET_SIZE) {
|
||||
BOOST_THROW_EXCEPTION(Error("Interest size exceeds maximum limit"));
|
||||
}
|
||||
NDN_LOG_DEBUG("<I " << *interestToExpress); // interestToExpress is guaranteed to have nonce
|
||||
|
||||
// If the same ioService thread, dispatch directly calls the method
|
||||
IO_CAPTURE_WEAK_IMPL(dispatch) {
|
||||
impl->asyncExpressInterest(interestToExpress, afterSatisfied, afterNacked, afterTimeout);
|
||||
impl->asyncExpressInterest(interest2, afterSatisfied, afterNacked, afterTimeout);
|
||||
} IO_CAPTURE_WEAK_IMPL_END
|
||||
|
||||
return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
|
||||
return reinterpret_cast<const PendingInterestId*>(interest2.get());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -209,60 +214,20 @@ Face::getNPendingInterests() const
|
||||
}
|
||||
|
||||
void
|
||||
Face::put(const Data& data)
|
||||
Face::put(Data data)
|
||||
{
|
||||
Block wire = data.wireEncode();
|
||||
|
||||
lp::Packet packet;
|
||||
bool hasLpFields = false;
|
||||
|
||||
shared_ptr<lp::CachePolicyTag> cachePolicyTag = data.getTag<lp::CachePolicyTag>();
|
||||
if (cachePolicyTag != nullptr) {
|
||||
packet.add<lp::CachePolicyField>(*cachePolicyTag);
|
||||
hasLpFields = true;
|
||||
}
|
||||
|
||||
shared_ptr<lp::CongestionMarkTag> congestionMarkTag = data.getTag<lp::CongestionMarkTag>();
|
||||
if (congestionMarkTag != nullptr) {
|
||||
packet.add<lp::CongestionMarkField>(*congestionMarkTag);
|
||||
hasLpFields = true;
|
||||
}
|
||||
|
||||
if (hasLpFields) {
|
||||
packet.add<lp::FragmentField>(std::make_pair(wire.begin(), wire.end()));
|
||||
wire = packet.wireEncode();
|
||||
}
|
||||
|
||||
if (wire.size() > MAX_NDN_PACKET_SIZE)
|
||||
BOOST_THROW_EXCEPTION(Error("Data size exceeds maximum limit"));
|
||||
|
||||
NDN_LOG_DEBUG("<D " << data.getName());
|
||||
IO_CAPTURE_WEAK_IMPL(dispatch) {
|
||||
impl->asyncSend(wire);
|
||||
impl->asyncPutData(data);
|
||||
} IO_CAPTURE_WEAK_IMPL_END
|
||||
}
|
||||
|
||||
void
|
||||
Face::put(const lp::Nack& nack)
|
||||
Face::put(lp::Nack nack)
|
||||
{
|
||||
lp::Packet packet;
|
||||
packet.add<lp::NackField>(nack.getHeader());
|
||||
const Block& interestWire = nack.getInterest().wireEncode();
|
||||
packet.add<lp::FragmentField>(std::make_pair(interestWire.begin(), interestWire.end()));
|
||||
|
||||
shared_ptr<lp::CongestionMarkTag> congestionMarkTag = nack.getTag<lp::CongestionMarkTag>();
|
||||
if (congestionMarkTag != nullptr) {
|
||||
packet.add<lp::CongestionMarkField>(*congestionMarkTag);
|
||||
}
|
||||
|
||||
Block wire = packet.wireEncode();
|
||||
|
||||
if (wire.size() > MAX_NDN_PACKET_SIZE)
|
||||
BOOST_THROW_EXCEPTION(Error("Nack size exceeds maximum limit"));
|
||||
|
||||
NDN_LOG_DEBUG("<N " << nack.getInterest() << '~' << nack.getHeader().getReason());
|
||||
IO_CAPTURE_WEAK_IMPL(dispatch) {
|
||||
impl->asyncSend(wire);
|
||||
impl->asyncPutNack(nack);
|
||||
} IO_CAPTURE_WEAK_IMPL_END
|
||||
}
|
||||
|
||||
|
||||
+40
-21
@@ -22,16 +22,14 @@
|
||||
#ifndef NDN_FACE_HPP
|
||||
#define NDN_FACE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include "data.hpp"
|
||||
#include "name.hpp"
|
||||
#include "interest.hpp"
|
||||
#include "interest-filter.hpp"
|
||||
#include "data.hpp"
|
||||
#include "encoding/nfd-constants.hpp"
|
||||
#include "lp/nack.hpp"
|
||||
#include "security/signing-info.hpp"
|
||||
#include "security/key-chain.hpp"
|
||||
#include "security/signing-info.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
@@ -107,6 +105,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Exception thrown when attempting to send a packet over size limit
|
||||
*/
|
||||
class OversizedPacketError : public Error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param pktType packet type, 'I' for Interest, 'D' for Data, 'N' for Nack
|
||||
* @param name packet name
|
||||
* @param wireSize wire encoding size
|
||||
*/
|
||||
OversizedPacketError(char pktType, const Name& name, size_t wireSize);
|
||||
|
||||
public:
|
||||
const char pktType;
|
||||
const Name name;
|
||||
const size_t wireSize;
|
||||
};
|
||||
|
||||
public: // constructors
|
||||
/**
|
||||
* @brief Create Face using given transport (or default transport if omitted)
|
||||
@@ -115,7 +133,7 @@ public: // constructors
|
||||
* determined from a FaceUri in NDN_CLIENT_TRANSPORT environ,
|
||||
* a FaceUri in configuration file 'transport' key, or UnixTransport.
|
||||
*
|
||||
* @throw ConfigFile::Error if @p transport is nullptr, and the configuration file cannot be
|
||||
* @throw ConfigFile::Error @p transport is nullptr, and the configuration file cannot be
|
||||
* parsed or specifies an unsupported protocol
|
||||
* @note shared_ptr is passed by value because ownership is shared with this class
|
||||
*/
|
||||
@@ -170,7 +188,7 @@ public: // constructors
|
||||
*
|
||||
* @sa Face(shared_ptr<Transport>)
|
||||
*
|
||||
* @throw ConfigFile::Error if @p transport is nullptr, and the configuration file cannot be
|
||||
* @throw ConfigFile::Error @p transport is nullptr, and the configuration file cannot be
|
||||
* parsed or specifies an unsupported protocol
|
||||
* @note shared_ptr is passed by value because ownership is shared with this class
|
||||
*/
|
||||
@@ -185,7 +203,7 @@ public: // constructors
|
||||
* @sa Face(boost::asio::io_service&)
|
||||
* @sa Face(shared_ptr<Transport>)
|
||||
*
|
||||
* @throw ConfigFile::Error if @p transport is nullptr, and the configuration file cannot be
|
||||
* @throw ConfigFile::Error @p transport is nullptr, and the configuration file cannot be
|
||||
* parsed or specifies an unsupported protocol
|
||||
* @note shared_ptr is passed by value because ownership is shared with this class
|
||||
*/
|
||||
@@ -201,7 +219,7 @@ public: // constructors
|
||||
* @sa Face(boost::asio::io_service&)
|
||||
* @sa Face(shared_ptr<Transport>, KeyChain&)
|
||||
*
|
||||
* @throw ConfigFile::Error if @p transport is nullptr, and the configuration file cannot be
|
||||
* @throw ConfigFile::Error @p transport is nullptr, and the configuration file cannot be
|
||||
* parsed or specifies an unsupported protocol
|
||||
* @note shared_ptr is passed by value because ownership is shared with this class
|
||||
*/
|
||||
@@ -219,6 +237,7 @@ public: // consumer
|
||||
* @param afterNacked function to be invoked if Network NACK is returned
|
||||
* @param afterTimeout function to be invoked if neither Data nor Network NACK
|
||||
* is returned within InterestLifetime
|
||||
* @throw OversizedPacketError encoded Interest size exceeds MAX_NDN_PACKET_SIZE
|
||||
*/
|
||||
const PendingInterestId*
|
||||
expressInterest(const Interest& interest,
|
||||
@@ -387,29 +406,27 @@ public: // producer
|
||||
const UnregisterPrefixSuccessCallback& onSuccess,
|
||||
const UnregisterPrefixFailureCallback& onFailure);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Publish data packet
|
||||
* @param data the Data; a copy will be made, so that the caller is not required to
|
||||
* maintain the argument unchanged
|
||||
*
|
||||
* This method can be called to satisfy the incoming Interest or to put Data packet into
|
||||
* the cache of the local NDN forwarder.
|
||||
* This method can be called to satisfy incoming Interests, or to add Data packet into the cache
|
||||
* of the local NDN forwarder if forwarder is configured to accept unsolicited Data.
|
||||
*
|
||||
* @param data Data packet to publish. It is highly recommended to use Data packet that
|
||||
* was created using make_shared<Data>(...). Otherwise, put() will make an
|
||||
* extra copy of the Data packet to ensure validity of published Data until
|
||||
* asynchronous put() operation finishes.
|
||||
*
|
||||
* @throw Error when Data size exceeds maximum limit (MAX_NDN_PACKET_SIZE)
|
||||
* @throw OversizedPacketError encoded Data size exceeds MAX_NDN_PACKET_SIZE
|
||||
*/
|
||||
void
|
||||
put(const Data& data);
|
||||
put(Data data);
|
||||
|
||||
/**
|
||||
* @brief sends a Network NACK
|
||||
* @brief Send a network NACK
|
||||
* @param nack the Nack; a copy will be made, so that the caller is not required to
|
||||
* maintain the argument unchanged
|
||||
* @throw OversizedPacketError encoded Nack size exceeds MAX_NDN_PACKET_SIZE
|
||||
*/
|
||||
void
|
||||
put(const lp::Nack& nack);
|
||||
put(lp::Nack nack);
|
||||
|
||||
public: // IO routine
|
||||
/**
|
||||
@@ -429,9 +446,11 @@ public: // IO routine
|
||||
* @param keepThread Keep thread in a blocked state (in event processing), even when
|
||||
* there are no outstanding events (e.g., no Interest/Data is expected)
|
||||
*
|
||||
* @throw This may throw an exception for reading data or in the callback for processing
|
||||
* @note This may throw an exception for reading data or in the callback for processing
|
||||
* the data. If you call this from an main event loop, you may want to catch and
|
||||
* log/disregard all exceptions.
|
||||
*
|
||||
* @throw OversizedPacketError encoded packet size exceeds MAX_NDN_PACKET_SIZE
|
||||
*/
|
||||
void
|
||||
processEvents(time::milliseconds timeout = time::milliseconds::zero(),
|
||||
|
||||
+11
-1
@@ -1,5 +1,5 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2013-2017 Regents of the University of California.
|
||||
*
|
||||
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
|
||||
@@ -58,6 +58,16 @@ public:
|
||||
void
|
||||
wireDecode(const Block& wire);
|
||||
|
||||
/**
|
||||
* \retval true packet has no field
|
||||
* \retval false packet has one or more fields
|
||||
*/
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return m_wire.elements_size() == 0;
|
||||
}
|
||||
|
||||
public: // field access
|
||||
/**
|
||||
* \return true if FIELD occurs one or more times
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "dummy-client-face.hpp"
|
||||
#include "../detail/lp-field-tag.hpp"
|
||||
#include "../lp/packet.hpp"
|
||||
#include "../lp/tags.hpp"
|
||||
#include "../mgmt/nfd/controller.hpp"
|
||||
@@ -217,16 +218,6 @@ DummyClientFace::enableRegistrationReply()
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Field, typename Tag, typename Packet>
|
||||
static void
|
||||
addFieldFromTag(lp::Packet& lpPacket, const Packet& packet)
|
||||
{
|
||||
shared_ptr<Tag> tag = static_cast<const TagHost&>(packet).getTag<Tag>();
|
||||
if (tag != nullptr) {
|
||||
lpPacket.add<Field>(*tag);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DummyClientFace::receive(const Interest& interest)
|
||||
{
|
||||
|
||||
+13
-11
@@ -150,9 +150,7 @@ BOOST_AUTO_TEST_CASE(Unix)
|
||||
bind(&FacesFixture::onData, this),
|
||||
bind(&FacesFixture::onNack, this),
|
||||
bind(&FacesFixture::onTimeout, this));
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(face.processEvents());
|
||||
|
||||
face.processEvents();
|
||||
BOOST_CHECK_EQUAL(nData, 1);
|
||||
BOOST_CHECK_EQUAL(nNacks, 0);
|
||||
BOOST_CHECK_EQUAL(nTimeouts, 0);
|
||||
@@ -162,25 +160,29 @@ BOOST_AUTO_TEST_CASE(Unix)
|
||||
bind(&FacesFixture::onData, this),
|
||||
bind(&FacesFixture::onNack, this),
|
||||
bind(&FacesFixture::onTimeout, this));
|
||||
face.processEvents();
|
||||
BOOST_CHECK_EQUAL(nData, 1);
|
||||
BOOST_CHECK_EQUAL(nNacks, 0);
|
||||
BOOST_CHECK_EQUAL(nTimeouts, 1);
|
||||
|
||||
Name veryLongName;
|
||||
for (size_t i = 0; i <= MAX_NDN_PACKET_SIZE / 10; i++) {
|
||||
veryLongName.append("0123456789");
|
||||
}
|
||||
|
||||
BOOST_CHECK_THROW(face.expressInterest(Interest(veryLongName), nullptr, nullptr, nullptr),
|
||||
Face::Error);
|
||||
BOOST_CHECK_THROW(do {
|
||||
face.expressInterest(Interest(veryLongName), nullptr, nullptr, nullptr);
|
||||
face.processEvents();
|
||||
} while (false), Face::OversizedPacketError);
|
||||
|
||||
shared_ptr<Data> data = make_shared<Data>(veryLongName);
|
||||
data->setContent(reinterpret_cast<const uint8_t*>("01234567890"), 10);
|
||||
m_keyChain.sign(*data);
|
||||
BOOST_CHECK_THROW(face.put(*data), Face::Error);
|
||||
BOOST_CHECK_THROW(do {
|
||||
face.put(*data);
|
||||
face.processEvents();
|
||||
} while (false), Face::OversizedPacketError);
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(face.processEvents());
|
||||
|
||||
BOOST_CHECK_EQUAL(nData, 1);
|
||||
BOOST_CHECK_EQUAL(nNacks, 0);
|
||||
BOOST_CHECK_EQUAL(nTimeouts, 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Tcp)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2013-2017 Regents of the University of California.
|
||||
*
|
||||
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
|
||||
@@ -34,24 +34,30 @@ BOOST_AUTO_TEST_CASE(FieldAccess)
|
||||
{
|
||||
Packet packet;
|
||||
|
||||
BOOST_CHECK(packet.empty());
|
||||
BOOST_CHECK(!packet.has<FragIndexField>());
|
||||
BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
|
||||
BOOST_CHECK_NO_THROW(packet.set<FragIndexField>(1234));
|
||||
|
||||
packet.set<FragIndexField>(1234);
|
||||
BOOST_CHECK(!packet.empty());
|
||||
BOOST_CHECK(packet.has<FragIndexField>());
|
||||
BOOST_CHECK_THROW(packet.add<FragIndexField>(5678), std::length_error);
|
||||
BOOST_CHECK_EQUAL(1, packet.count<FragIndexField>());
|
||||
BOOST_CHECK_EQUAL(1234, packet.get<FragIndexField>(0));
|
||||
BOOST_CHECK_THROW(packet.get<FragIndexField>(1), std::out_of_range);
|
||||
BOOST_CHECK_THROW(packet.remove<FragIndexField>(1), std::out_of_range);
|
||||
BOOST_CHECK_NO_THROW(packet.remove<FragIndexField>(0));
|
||||
|
||||
packet.remove<FragIndexField>(0);
|
||||
BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
|
||||
BOOST_CHECK_NO_THROW(packet.add<FragIndexField>(832));
|
||||
std::vector<uint64_t> fragIndexes;
|
||||
BOOST_REQUIRE_NO_THROW(fragIndexes = packet.list<FragIndexField>());
|
||||
|
||||
packet.add<FragIndexField>(832);
|
||||
std::vector<uint64_t> fragIndexes = packet.list<FragIndexField>();
|
||||
BOOST_CHECK_EQUAL(1, fragIndexes.size());
|
||||
BOOST_CHECK_EQUAL(832, fragIndexes.at(0));
|
||||
BOOST_CHECK_NO_THROW(packet.clear<FragIndexField>());
|
||||
|
||||
packet.clear<FragIndexField>();
|
||||
BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
|
||||
BOOST_CHECK(packet.empty());
|
||||
}
|
||||
|
||||
/// \todo test field access methods with a REPEATABLE field
|
||||
|
||||
Reference in new issue
Block a user