face: perform wire format encoding in frontend class
Face::put encodes Data and Nack into wire format before passing to Impl class,
so that Face::put(const Data&) doesn't require the Data to be managed by a
shared_ptr.
For the common case of sending Data without other NDNLPv2 headers, this commit
adds an optimization that the Data is not copied into an LpPacket, but directly
encodes into wire format.
refs #3678
Change-Id: I7ac7bb574a5cb3b07f6c62060809c94ff1cf3dee
diff --git a/src/detail/face-impl.hpp b/src/detail/face-impl.hpp
index fa5f989..92f102f 100644
--- a/src/detail/face-impl.hpp
+++ b/src/detail/face-impl.hpp
@@ -173,35 +173,10 @@
}
void
- asyncPutData(const shared_ptr<const Data>& data)
+ asyncSend(const Block& wire)
{
this->ensureConnected(true);
-
- lp::Packet packet;
-
- shared_ptr<lp::CachePolicyTag> cachePolicyTag = data->getTag<lp::CachePolicyTag>();
- if (cachePolicyTag != nullptr) {
- packet.add<lp::CachePolicyField>(*cachePolicyTag);
- }
-
- packet.add<lp::FragmentField>(std::make_pair(data->wireEncode().begin(),
- data->wireEncode().end()));
-
- m_face.m_transport->send(packet.wireEncode());
- }
-
- void
- asyncPutNack(shared_ptr<const lp::Nack> nack)
- {
- this->ensureConnected(true);
-
- lp::Packet packet;
- packet.add<lp::NackField>(nack->getHeader());
-
- Block interest = nack->getInterest().wireEncode();
- packet.add<lp::FragmentField>(std::make_pair(interest.begin(), interest.end()));
-
- m_face.m_transport->send(packet.wireEncode());
+ m_face.m_transport->send(wire);
}
public: // prefix registration
diff --git a/src/face.cpp b/src/face.cpp
index 537f1b2..fbaee26 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -238,33 +238,39 @@
void
Face::put(const Data& data)
{
- // Use original `data`, since wire format should already exist for the original Data
- if (data.wireEncode().size() > MAX_NDN_PACKET_SIZE)
+ Block wire = data.wireEncode();
+
+ shared_ptr<lp::CachePolicyTag> cachePolicyTag = data.getTag<lp::CachePolicyTag>();
+ if (cachePolicyTag != nullptr) {
+ lp::Packet packet;
+ packet.add<lp::CachePolicyField>(*cachePolicyTag);
+ 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"));
- shared_ptr<const Data> dataPtr;
- try {
- dataPtr = data.shared_from_this();
- }
- catch (const bad_weak_ptr& e) {
- std::cerr << "Face::put WARNING: the supplied Data should be created using make_shared<Data>()"
- << std::endl;
- dataPtr = make_shared<Data>(data);
- }
-
- // If the same ioService thread, dispatch directly calls the method
IO_CAPTURE_WEAK_IMPL(dispatch) {
- impl->asyncPutData(dataPtr);
+ impl->asyncSend(wire);
} IO_CAPTURE_WEAK_IMPL_END
}
void
Face::put(const lp::Nack& nack)
{
- auto nackPtr = make_shared<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()));
+
+ Block wire = packet.wireEncode();
+
+ if (wire.size() > MAX_NDN_PACKET_SIZE)
+ BOOST_THROW_EXCEPTION(Error("Nack size exceeds maximum limit"));
IO_CAPTURE_WEAK_IMPL(dispatch) {
- impl->asyncPutNack(nackPtr);
+ impl->asyncSend(wire);
} IO_CAPTURE_WEAK_IMPL_END
}