blob: 657fc028dd918d38d44064724593de1ad84f63fe [file] [log] [blame]
Junxiao Shia60d9362014-11-12 09:38:21 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2ed9e072017-08-13 16:45:48 +00002/*
Davide Pesavento3b101d02018-07-21 22:44:09 -04003 * Copyright (c) 2013-2018 Regents of the University of California.
Junxiao Shia60d9362014-11-12 09:38:21 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "dummy-client-face.hpp"
Junxiao Shib6e276f2017-08-14 20:10:04 +000023#include "../detail/lp-field-tag.hpp"
Junxiao Shic828dfc2016-09-15 13:26:22 +000024#include "../lp/packet.hpp"
Junxiao Shi7357ef22016-09-07 02:39:37 +000025#include "../lp/tags.hpp"
26#include "../mgmt/nfd/controller.hpp"
27#include "../mgmt/nfd/control-response.hpp"
Junxiao Shia60d9362014-11-12 09:38:21 -070028#include "../transport/transport.hpp"
Junxiao Shia60d9362014-11-12 09:38:21 -070029
Davide Pesavento537dc3a2016-02-18 19:35:26 +010030#include <boost/asio/io_service.hpp>
31
Junxiao Shia60d9362014-11-12 09:38:21 -070032namespace ndn {
33namespace util {
34
Junxiao Shia60d9362014-11-12 09:38:21 -070035class DummyClientFace::Transport : public ndn::Transport
36{
37public:
38 void
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020039 receive(Block block) const
Junxiao Shia60d9362014-11-12 09:38:21 -070040 {
Eric Newberry83872fd2015-08-06 17:01:24 -070041 block.encode();
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020042 if (m_receiveCallback) {
Junxiao Shia60d9362014-11-12 09:38:21 -070043 m_receiveCallback(block);
Eric Newberry83872fd2015-08-06 17:01:24 -070044 }
Junxiao Shia60d9362014-11-12 09:38:21 -070045 }
46
Davide Pesavento57c07df2016-12-11 18:41:45 -050047 void
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020048 close() override
Junxiao Shia60d9362014-11-12 09:38:21 -070049 {
50 }
51
Davide Pesavento57c07df2016-12-11 18:41:45 -050052 void
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020053 pause() override
Junxiao Shia60d9362014-11-12 09:38:21 -070054 {
55 }
56
Davide Pesavento57c07df2016-12-11 18:41:45 -050057 void
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020058 resume() override
Junxiao Shia60d9362014-11-12 09:38:21 -070059 {
60 }
61
Davide Pesavento57c07df2016-12-11 18:41:45 -050062 void
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020063 send(const Block& wire) override
Junxiao Shia60d9362014-11-12 09:38:21 -070064 {
Junxiao Shi27913b42014-12-23 14:49:38 -070065 onSendBlock(wire);
Junxiao Shia60d9362014-11-12 09:38:21 -070066 }
67
Davide Pesavento57c07df2016-12-11 18:41:45 -050068 void
Davide Pesaventoaeeb3fc2016-08-14 03:40:02 +020069 send(const Block& header, const Block& payload) override
Junxiao Shia60d9362014-11-12 09:38:21 -070070 {
Alexander Afanasyevea719672015-02-10 20:25:23 -080071 EncodingBuffer encoder(header.size() + payload.size(), header.size() + payload.size());
72 encoder.appendByteArray(header.wire(), header.size());
73 encoder.appendByteArray(payload.wire(), payload.size());
74
75 this->send(encoder.block());
Junxiao Shia60d9362014-11-12 09:38:21 -070076 }
77
78 boost::asio::io_service&
79 getIoService()
80 {
81 return *m_ioService;
82 }
83
Junxiao Shi27913b42014-12-23 14:49:38 -070084public:
85 Signal<Transport, Block> onSendBlock;
Junxiao Shia60d9362014-11-12 09:38:21 -070086};
87
Zhiyi Zhang34429cc2017-01-05 17:07:28 -080088struct DummyClientFace::BroadcastLink
89{
90 std::vector<DummyClientFace*> faces;
91};
92
93DummyClientFace::AlreadyLinkedError::AlreadyLinkedError()
94 : Error("Face has already been linked to another face")
95{
96}
97
Davide Pesavento3b101d02018-07-21 22:44:09 -040098DummyClientFace::DummyClientFace(const Options& options)
Alexander Afanasyev3a6da362015-12-29 20:31:03 -080099 : Face(make_shared<DummyClientFace::Transport>())
Davide Pesavento3b101d02018-07-21 22:44:09 -0400100 , m_internalKeyChain(make_unique<KeyChain>())
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700101 , m_keyChain(*m_internalKeyChain)
102{
103 this->construct(options);
104}
105
Davide Pesavento3b101d02018-07-21 22:44:09 -0400106DummyClientFace::DummyClientFace(KeyChain& keyChain, const Options& options)
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700107 : Face(make_shared<DummyClientFace::Transport>(), keyChain)
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700108 , m_keyChain(keyChain)
Junxiao Shia60d9362014-11-12 09:38:21 -0700109{
110 this->construct(options);
111}
112
Davide Pesavento3b101d02018-07-21 22:44:09 -0400113DummyClientFace::DummyClientFace(boost::asio::io_service& ioService, const Options& options)
Alexander Afanasyev3a6da362015-12-29 20:31:03 -0800114 : Face(make_shared<DummyClientFace::Transport>(), ioService)
Davide Pesavento3b101d02018-07-21 22:44:09 -0400115 , m_internalKeyChain(make_unique<KeyChain>())
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700116 , m_keyChain(*m_internalKeyChain)
117{
118 this->construct(options);
119}
120
Davide Pesavento3b101d02018-07-21 22:44:09 -0400121DummyClientFace::DummyClientFace(boost::asio::io_service& ioService, KeyChain& keyChain, const Options& options)
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700122 : Face(make_shared<DummyClientFace::Transport>(), ioService, keyChain)
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700123 , m_keyChain(keyChain)
Junxiao Shia60d9362014-11-12 09:38:21 -0700124{
125 this->construct(options);
126}
127
Zhiyi Zhang34429cc2017-01-05 17:07:28 -0800128DummyClientFace::~DummyClientFace()
129{
130 unlink();
131}
132
Junxiao Shia60d9362014-11-12 09:38:21 -0700133void
134DummyClientFace::construct(const Options& options)
135{
Alexander Afanasyev3a6da362015-12-29 20:31:03 -0800136 static_pointer_cast<Transport>(getTransport())->onSendBlock.connect([this] (const Block& blockFromDaemon) {
Eric Newberrye3e25052015-11-28 20:37:08 -0700137 Block packet(blockFromDaemon);
138 packet.encode();
139 lp::Packet lpPacket(packet);
Alexander Afanasyevea719672015-02-10 20:25:23 -0800140
Eric Newberrye3e25052015-11-28 20:37:08 -0700141 Buffer::const_iterator begin, end;
142 std::tie(begin, end) = lpPacket.get<lp::FragmentField>();
143 Block block(&*begin, std::distance(begin, end));
Alexander Afanasyevea719672015-02-10 20:25:23 -0800144
Eric Newberrye3e25052015-11-28 20:37:08 -0700145 if (block.type() == tlv::Interest) {
146 shared_ptr<Interest> interest = make_shared<Interest>(block);
147 if (lpPacket.has<lp::NackField>()) {
148 shared_ptr<lp::Nack> nack = make_shared<lp::Nack>(std::move(*interest));
149 nack->setHeader(lpPacket.get<lp::NackField>());
Junxiao Shib38e6d42017-08-16 16:15:28 +0000150 addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(*nack, lpPacket);
Eric Newberrye3e25052015-11-28 20:37:08 -0700151 onSendNack(*nack);
Eric Newberry83872fd2015-08-06 17:01:24 -0700152 }
Eric Newberrye3e25052015-11-28 20:37:08 -0700153 else {
Junxiao Shib38e6d42017-08-16 16:15:28 +0000154 addTagFromField<lp::NextHopFaceIdTag, lp::NextHopFaceIdField>(*interest, lpPacket);
155 addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(*interest, lpPacket);
Eric Newberrye3e25052015-11-28 20:37:08 -0700156 onSendInterest(*interest);
Eric Newberry83872fd2015-08-06 17:01:24 -0700157 }
Junxiao Shi27913b42014-12-23 14:49:38 -0700158 }
Eric Newberrye3e25052015-11-28 20:37:08 -0700159 else if (block.type() == tlv::Data) {
160 shared_ptr<Data> data = make_shared<Data>(block);
Junxiao Shib38e6d42017-08-16 16:15:28 +0000161 addTagFromField<lp::CachePolicyTag, lp::CachePolicyField>(*data, lpPacket);
162 addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(*data, lpPacket);
Eric Newberrye3e25052015-11-28 20:37:08 -0700163 onSendData(*data);
Junxiao Shi27913b42014-12-23 14:49:38 -0700164 }
165 });
166
Junxiao Shia60d9362014-11-12 09:38:21 -0700167 if (options.enablePacketLogging)
168 this->enablePacketLogging();
169
170 if (options.enableRegistrationReply)
171 this->enableRegistrationReply();
Junxiao Shic828dfc2016-09-15 13:26:22 +0000172
173 m_processEventsOverride = options.processEventsOverride;
Zhiyi Zhang34429cc2017-01-05 17:07:28 -0800174
175 enableBroadcastLink();
176}
177
178void
179DummyClientFace::enableBroadcastLink()
180{
181 this->onSendInterest.connect([this] (const Interest& interest) {
182 if (m_bcastLink != nullptr) {
183 for (auto otherFace : m_bcastLink->faces) {
184 if (otherFace != this) {
185 otherFace->receive(interest);
186 }
187 }
188 }
189 });
190 this->onSendData.connect([this] (const Data& data) {
191 if (m_bcastLink != nullptr) {
192 for (auto otherFace : m_bcastLink->faces) {
193 if (otherFace != this) {
194 otherFace->receive(data);
195 }
196 }
197 }
198 });
199 this->onSendNack.connect([this] (const lp::Nack& nack) {
200 if (m_bcastLink != nullptr) {
201 for (auto otherFace : m_bcastLink->faces) {
202 if (otherFace != this) {
203 otherFace->receive(nack);
204 }
205 }
206 }
207 });
Junxiao Shia60d9362014-11-12 09:38:21 -0700208}
209
210void
211DummyClientFace::enablePacketLogging()
212{
Junxiao Shi27913b42014-12-23 14:49:38 -0700213 onSendInterest.connect([this] (const Interest& interest) {
214 this->sentInterests.push_back(interest);
215 });
216 onSendData.connect([this] (const Data& data) {
Alexander Afanasyev3a6da362015-12-29 20:31:03 -0800217 this->sentData.push_back(data);
Junxiao Shi27913b42014-12-23 14:49:38 -0700218 });
Eric Newberry83872fd2015-08-06 17:01:24 -0700219 onSendNack.connect([this] (const lp::Nack& nack) {
220 this->sentNacks.push_back(nack);
221 });
Junxiao Shia60d9362014-11-12 09:38:21 -0700222}
223
224void
225DummyClientFace::enableRegistrationReply()
226{
Junxiao Shi27913b42014-12-23 14:49:38 -0700227 onSendInterest.connect([this] (const Interest& interest) {
Junxiao Shia60d9362014-11-12 09:38:21 -0700228 static const Name localhostRegistration("/localhost/nfd/rib");
229 if (!localhostRegistration.isPrefixOf(interest.getName()))
230 return;
231
232 nfd::ControlParameters params(interest.getName().get(-5).blockFromValue());
233 params.setFaceId(1);
Davide Pesaventoe8e48c22017-04-13 00:35:33 -0400234 params.setOrigin(nfd::ROUTE_ORIGIN_APP);
Junxiao Shia60d9362014-11-12 09:38:21 -0700235 if (interest.getName().get(3) == name::Component("register")) {
236 params.setCost(0);
237 }
238
239 nfd::ControlResponse resp;
240 resp.setCode(200);
241 resp.setBody(params.wireEncode());
242
243 shared_ptr<Data> data = make_shared<Data>(interest.getName());
244 data->setContent(resp.wireEncode());
245
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -0700246 m_keyChain.sign(*data, security::SigningInfo(security::SigningInfo::SIGNER_TYPE_SHA256));
Junxiao Shia60d9362014-11-12 09:38:21 -0700247
248 this->getIoService().post([this, data] { this->receive(*data); });
Junxiao Shi27913b42014-12-23 14:49:38 -0700249 });
Junxiao Shia60d9362014-11-12 09:38:21 -0700250}
251
Junxiao Shia60d9362014-11-12 09:38:21 -0700252void
Zhiyi Zhang9cbd0102017-01-03 11:03:01 -0800253DummyClientFace::receive(const Interest& interest)
Junxiao Shia60d9362014-11-12 09:38:21 -0700254{
Zhiyi Zhang9cbd0102017-01-03 11:03:01 -0800255 lp::Packet lpPacket(interest.wireEncode());
Alexander Afanasyevea719672015-02-10 20:25:23 -0800256
Zhiyi Zhang9cbd0102017-01-03 11:03:01 -0800257 addFieldFromTag<lp::IncomingFaceIdField, lp::IncomingFaceIdTag>(lpPacket, interest);
258 addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest);
259 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, interest);
Eric Newberry83872fd2015-08-06 17:01:24 -0700260
Alexander Afanasyev3a6da362015-12-29 20:31:03 -0800261 static_pointer_cast<Transport>(getTransport())->receive(lpPacket.wireEncode());
Junxiao Shia60d9362014-11-12 09:38:21 -0700262}
263
Eric Newberry83872fd2015-08-06 17:01:24 -0700264void
Zhiyi Zhang9cbd0102017-01-03 11:03:01 -0800265DummyClientFace::receive(const Data& data)
266{
267 lp::Packet lpPacket(data.wireEncode());
268
269 addFieldFromTag<lp::IncomingFaceIdField, lp::IncomingFaceIdTag>(lpPacket, data);
270 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, data);
271
272 static_pointer_cast<Transport>(getTransport())->receive(lpPacket.wireEncode());
273}
274
275void
276DummyClientFace::receive(const lp::Nack& nack)
Eric Newberry83872fd2015-08-06 17:01:24 -0700277{
278 lp::Packet lpPacket;
279 lpPacket.add<lp::NackField>(nack.getHeader());
280 Block interest = nack.getInterest().wireEncode();
281 lpPacket.add<lp::FragmentField>(make_pair(interest.begin(), interest.end()));
282
Zhiyi Zhang9cbd0102017-01-03 11:03:01 -0800283 addFieldFromTag<lp::IncomingFaceIdField, lp::IncomingFaceIdTag>(lpPacket, nack);
284 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, nack);
Eric Newberry83872fd2015-08-06 17:01:24 -0700285
Alexander Afanasyev3a6da362015-12-29 20:31:03 -0800286 static_pointer_cast<Transport>(getTransport())->receive(lpPacket.wireEncode());
Eric Newberry83872fd2015-08-06 17:01:24 -0700287}
Junxiao Shia60d9362014-11-12 09:38:21 -0700288
Junxiao Shic828dfc2016-09-15 13:26:22 +0000289void
Zhiyi Zhang34429cc2017-01-05 17:07:28 -0800290DummyClientFace::linkTo(DummyClientFace& other)
291{
292 if (m_bcastLink != nullptr && other.m_bcastLink != nullptr) {
293 if (m_bcastLink != other.m_bcastLink) {
294 // already on different links
295 BOOST_THROW_EXCEPTION(AlreadyLinkedError());
296 }
297 }
298 else if (m_bcastLink == nullptr && other.m_bcastLink != nullptr) {
299 m_bcastLink = other.m_bcastLink;
300 m_bcastLink->faces.push_back(this);
301 }
302 else if (m_bcastLink != nullptr && other.m_bcastLink == nullptr) {
303 other.m_bcastLink = m_bcastLink;
304 m_bcastLink->faces.push_back(&other);
305 }
306 else {
307 m_bcastLink = other.m_bcastLink = make_shared<BroadcastLink>();
308 m_bcastLink->faces.push_back(this);
309 m_bcastLink->faces.push_back(&other);
310 }
311}
312
313void
314DummyClientFace::unlink()
315{
316 if (m_bcastLink == nullptr) {
317 return;
318 }
319
320 auto it = std::find(m_bcastLink->faces.begin(), m_bcastLink->faces.end(), this);
321 BOOST_ASSERT(it != m_bcastLink->faces.end());
322 m_bcastLink->faces.erase(it);
323
324 if (m_bcastLink->faces.size() == 1) {
325 m_bcastLink->faces[0]->m_bcastLink = nullptr;
326 m_bcastLink->faces.clear();
327 }
328 m_bcastLink = nullptr;
329}
330
331void
Junxiao Shi2ed9e072017-08-13 16:45:48 +0000332DummyClientFace::doProcessEvents(time::milliseconds timeout, bool keepThread)
Junxiao Shic828dfc2016-09-15 13:26:22 +0000333{
334 if (m_processEventsOverride != nullptr) {
335 m_processEventsOverride(timeout);
336 }
337 else {
338 this->Face::doProcessEvents(timeout, keepThread);
339 }
340}
341
Junxiao Shia60d9362014-11-12 09:38:21 -0700342} // namespace util
343} // namespace ndn