24 #include "ndn-cxx/impl/lp-field-tag.hpp"
32 #include <boost/asio/io_context.hpp>
33 #include <boost/asio/post.hpp>
42 receive(Block block)
const
45 if (m_receiveCallback) {
46 m_receiveCallback(block);
51 send(
const Block& block)
final
72 signal::Signal<DummyTransport, Block> onSendBlock;
77 struct DummyClientFace::BroadcastLink
79 std::vector<DummyClientFace*> faces;
83 :
Error(
"Face has already been linked to another face")
88 :
Face(make_shared<DummyTransport>())
89 , m_internalKeyChain(make_unique<
KeyChain>())
90 , m_keyChain(*m_internalKeyChain)
92 this->construct(options);
96 :
Face(make_shared<DummyTransport>(), keyChain)
97 , m_keyChain(keyChain)
99 this->construct(options);
103 :
Face(make_shared<DummyTransport>(), ioCtx)
104 , m_internalKeyChain(make_unique<
KeyChain>())
105 , m_keyChain(*m_internalKeyChain)
107 this->construct(options);
111 :
Face(make_shared<DummyTransport>(), ioCtx, keyChain)
112 , m_keyChain(keyChain)
114 this->construct(options);
123 DummyClientFace::construct(
const Options& options)
125 static_cast<DummyTransport&
>(
getTransport()).onSendBlock.connect([
this] (
Block packet) {
129 Block block({frag.first, frag.second});
132 auto interest = make_shared<Interest>(block);
134 auto nack = make_shared<lp::Nack>(std::move(*interest));
136 addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(*nack, lpPacket);
140 addTagFromField<lp::NextHopFaceIdTag, lp::NextHopFaceIdField>(*interest, lpPacket);
141 addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(*interest, lpPacket);
146 auto data = make_shared<Data>(block);
147 addTagFromField<lp::CachePolicyTag, lp::CachePolicyField>(*data, lpPacket);
148 addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(*data, lpPacket);
153 if (options.enablePacketLogging)
154 enablePacketLogging();
156 if (options.enableRegistrationReply)
157 enableRegistrationReply(options.registrationReplyFaceId);
159 m_processEventsOverride = options.processEventsOverride;
161 enableBroadcastLink();
165 DummyClientFace::enableBroadcastLink()
168 if (m_bcastLink !=
nullptr) {
169 for (
auto otherFace : m_bcastLink->faces) {
170 if (otherFace != this) {
171 otherFace->receive(interest);
176 this->onSendData.connect([
this] (
const Data& data) {
177 if (m_bcastLink !=
nullptr) {
178 for (
auto otherFace : m_bcastLink->faces) {
179 if (otherFace != this) {
180 otherFace->receive(data);
185 this->onSendNack.connect([
this] (
const lp::Nack& nack) {
186 if (m_bcastLink !=
nullptr) {
187 for (
auto otherFace : m_bcastLink->faces) {
188 if (otherFace != this) {
189 otherFace->receive(nack);
197 DummyClientFace::enablePacketLogging()
199 onSendInterest.connect([
this] (
const Interest& interest) {
200 this->sentInterests.push_back(interest);
202 onSendData.connect([
this] (
const Data& data) {
203 this->sentData.push_back(data);
205 onSendNack.connect([
this] (
const lp::Nack& nack) {
206 this->sentNacks.push_back(nack);
211 DummyClientFace::enableRegistrationReply(uint64_t faceId)
213 onSendInterest.connect([=] (
const Interest& interest) {
214 static const Name localhostRibPrefix(
"/localhost/nfd/rib");
215 static const name::Component registerVerb(
"register");
216 const auto& name = interest.getName();
217 if (name.size() <= 4 || !localhostRibPrefix.isPrefixOf(name))
221 if (!params.hasFaceId()) {
222 params.setFaceId(faceId);
224 if (!params.hasOrigin()) {
227 if (!params.hasCost() && name[3] == registerVerb) {
233 resp.
setBody(params.wireEncode());
235 auto data = make_shared<Data>(name);
236 data->setContent(resp.wireEncode());
237 m_keyChain.sign(*data, security::SigningInfo(security::SigningInfo::SIGNER_TYPE_SHA256));
238 boost::asio::post(getIoContext(), [
this, data] { this->receive(*data); });
247 addFieldFromTag<lp::IncomingFaceIdField, lp::IncomingFaceIdTag>(lpPacket, interest);
248 addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest);
249 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, interest);
251 static_cast<DummyTransport&
>(getTransport()).receive(lpPacket.
wireEncode());
255 DummyClientFace::receive(
const Data& data)
259 addFieldFromTag<lp::IncomingFaceIdField, lp::IncomingFaceIdTag>(lpPacket, data);
260 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, data);
262 static_cast<DummyTransport&
>(getTransport()).receive(lpPacket.
wireEncode());
273 addFieldFromTag<lp::IncomingFaceIdField, lp::IncomingFaceIdTag>(lpPacket, nack);
274 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, nack);
276 static_cast<DummyTransport&
>(getTransport()).receive(lpPacket.
wireEncode());
282 if (m_bcastLink !=
nullptr && other.m_bcastLink !=
nullptr) {
283 if (m_bcastLink != other.m_bcastLink) {
288 else if (m_bcastLink ==
nullptr && other.m_bcastLink !=
nullptr) {
289 m_bcastLink = other.m_bcastLink;
290 m_bcastLink->faces.push_back(
this);
292 else if (m_bcastLink !=
nullptr && other.m_bcastLink ==
nullptr) {
293 other.m_bcastLink = m_bcastLink;
294 m_bcastLink->faces.push_back(&other);
297 m_bcastLink = other.m_bcastLink = make_shared<BroadcastLink>();
298 m_bcastLink->faces.push_back(
this);
299 m_bcastLink->faces.push_back(&other);
304 DummyClientFace::unlink()
306 if (m_bcastLink ==
nullptr) {
310 auto it = std::find(m_bcastLink->faces.begin(), m_bcastLink->faces.end(),
this);
311 BOOST_ASSERT(it != m_bcastLink->faces.end());
312 m_bcastLink->faces.erase(it);
314 if (m_bcastLink->faces.size() == 1) {
315 m_bcastLink->faces[0]->m_bcastLink =
nullptr;
316 m_bcastLink->faces.clear();
318 m_bcastLink =
nullptr;
324 if (m_processEventsOverride !=
nullptr) {
325 m_processEventsOverride(timeout);
328 Face::doProcessEvents(timeout, keepRunning);
Represents a TLV element of the NDN packet format.
void encode()
Encode sub-elements into TLV-VALUE.
Represents a Data packet.
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Prepend wire encoding to encoder.
A client-side face for unit testing.
signal::Signal< DummyClientFace, Interest > onSendInterest
Emitted whenever an Interest is sent.
~DummyClientFace() override
signal::Signal< DummyClientFace, lp::Nack > onSendNack
Emitted whenever a Nack is sent.
signal::Signal< DummyClientFace, Data > onSendData
Emitted whenever a Data packet is sent.
DummyClientFace(const Options &options={})
Create a dummy face with an internal I/O context.
void unlink()
Unlink the broadcast medium if previously linked.
Provide a communication channel with local or remote NDN forwarder.
Transport & getTransport() const
Returns the underlying transport.
Represents an Interest packet.
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Prepend wire encoding to encoder.
Provides a "TLV-oriented" delivery service.
Represents a Network Nack.
const Interest & getInterest() const
const NackHeader & getHeader() const
Packet & add(const typename FIELD::ValueType &value)
Add a FIELD with value.
Block wireEncode() const
Encode packet into wire format.
ControlResponse & setBody(const Block &body)
ControlResponse & setCode(uint32_t code)
The main interface for signing key management.
FieldDecl< field_location_tags::Header, NackHeader, tlv::Nack > NackField
mgmt::ControlResponse ControlResponse
::boost::chrono::milliseconds milliseconds
Options for DummyClientFace.