blob: 5ebec16756c84e88f21c712b91bf2d5a30271294 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -07002/**
Alexander Afanasyev9d158f02015-02-17 21:30:19 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070020 */
21
22#ifndef NDN_DETAIL_FACE_IMPL_HPP
23#define NDN_DETAIL_FACE_IMPL_HPP
24
25#include "../common.hpp"
26#include "../face.hpp"
27
28#include "registered-prefix.hpp"
29#include "pending-interest.hpp"
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080030#include "container-with-on-empty-signal.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070031
32#include "../util/scheduler.hpp"
33#include "../util/config-file.hpp"
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080034#include "../util/signal.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070035
Junxiao Shi0fa28452014-12-13 22:02:36 -070036#include "../transport/transport.hpp"
37#include "../transport/unix-transport.hpp"
38#include "../transport/tcp-transport.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070039
Junxiao Shi0fa28452014-12-13 22:02:36 -070040#include "../management/nfd-controller.hpp"
41#include "../management/nfd-command-options.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070042
Alexander Afanasyeve9741322015-08-19 23:04:52 -070043#include <ns3/ptr.h>
44#include <ns3/node.h>
45#include <ns3/node-list.h>
46#include <ns3/ndnSIM/model/ndn-l3-protocol.hpp>
47
48#include "ns3/ndnSIM/NFD/daemon/face/local-face.hpp"
49
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070050namespace ndn {
51
52class Face::Impl : noncopyable
53{
54public:
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080055 typedef ContainerWithOnEmptySignal<shared_ptr<PendingInterest>> PendingInterestTable;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070056 typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080057 typedef ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>> RegisteredPrefixTable;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070058
Alexander Afanasyeve9741322015-08-19 23:04:52 -070059 class NfdFace : public ::nfd::LocalFace
60 {
61 public:
62 NfdFace(Impl& face, const ::nfd::FaceUri& localUri, const ::nfd::FaceUri& remoteUri)
63 : ::nfd::LocalFace(localUri, remoteUri)
64 , m_appFaceImpl(face)
65 {
66 }
67
68 public: // from ::nfd::LocalFace
69 /**
70 * @brief Send Interest towards application
71 */
72 virtual void
73 sendInterest(const Interest& interest)
74 {
75 NS_LOG_DEBUG("<< Interest " << interest);
76 shared_ptr<const Interest> interestPtr = interest.shared_from_this();
77 m_appFaceImpl.m_scheduler.scheduleEvent(time::seconds(0), [this, interestPtr] {
78 m_appFaceImpl.processInterestFilters(*interestPtr);
79 });
80 }
81
82 /**
83 * @brief Send Data towards application
84 */
85 virtual void
86 sendData(const Data& data)
87 {
88 NS_LOG_DEBUG("<< Data " << data.getName());
89 shared_ptr<const Data> dataPtr = data.shared_from_this();
90 m_appFaceImpl.m_scheduler.scheduleEvent(time::seconds(0), [this, dataPtr] {
91 m_appFaceImpl.satisfyPendingInterests(*dataPtr);
92 });
93 }
94
95 /** \brief Close the face
96 *
97 * This terminates all communication on the face and cause
98 * onFail() method event to be invoked
99 */
100 virtual void
101 close()
102 {
103 this->fail("close");
104 }
105
106 private:
107 friend class Impl;
108 Impl& m_appFaceImpl;
109 };
110
111 ////////////////////////////////////////////////////////////////////////
112
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700113 explicit
114 Impl(Face& face)
115 : m_face(face)
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800116 , m_scheduler(m_face.getIoService())
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700117 {
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700118 ns3::Ptr<ns3::Node> node = ns3::NodeList::GetNode(ns3::Simulator::GetContext());
119 NS_ASSERT_MSG(node->GetObject<ns3::ndn::L3Protocol>() != 0,
120 "NDN stack should be installed on the node " << node);
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800121
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700122 auto uri = ::nfd::FaceUri("ndnFace://" + boost::lexical_cast<std::string>(node->GetId()));
123 m_nfdFace = make_shared<NfdFace>(*this, uri, uri);
124
125 node->GetObject<ns3::ndn::L3Protocol>()->addFace(m_nfdFace);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700126 }
127
128 /////////////////////////////////////////////////////////////////////////////////////////////////
129 /////////////////////////////////////////////////////////////////////////////////////////////////
130
131 void
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700132 satisfyPendingInterests(const Data& data)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700133 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800134 for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
135 if ((*entry)->getInterest().matchesData(data)) {
136 shared_ptr<PendingInterest> matchedEntry = *entry;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700137
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800138 entry = m_pendingInterestTable.erase(entry);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700139
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800140 matchedEntry->invokeDataCallback(data);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700141 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800142 else
143 ++entry;
144 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700145 }
146
147 void
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700148 processInterestFilters(const Interest& interest)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700149 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800150 for (const auto& filter : m_interestFilterTable) {
151 if (filter->doesMatch(interest.getName())) {
152 filter->invokeInterestCallback(interest);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700153 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800154 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700155 }
156
157 /////////////////////////////////////////////////////////////////////////////////////////////////
158 /////////////////////////////////////////////////////////////////////////////////////////////////
159
160 void
Junxiao Shia1ea5062014-12-27 22:33:39 -0700161 asyncExpressInterest(const shared_ptr<const Interest>& interest,
162 const OnData& onData, const OnTimeout& onTimeout)
163 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800164 auto entry =
165 m_pendingInterestTable.insert(make_shared<PendingInterest>(interest,
166 onData, onTimeout,
167 ref(m_scheduler))).first;
168 (*entry)->setDeleter([this, entry] { m_pendingInterestTable.erase(entry); });
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700169
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700170 m_nfdFace->emitSignal(onReceiveInterest, *interest);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700171 }
172
173 void
174 asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
175 {
176 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
177 }
178
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700179 void
180 asyncPutData(const shared_ptr<const Data>& data)
181 {
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700182 m_nfdFace->emitSignal(onReceiveData, *data);
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700183 }
184
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700185 /////////////////////////////////////////////////////////////////////////////////////////////////
186 /////////////////////////////////////////////////////////////////////////////////////////////////
187
188 void
189 asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord)
190 {
191 m_interestFilterTable.push_back(interestFilterRecord);
192 }
193
194 void
195 asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
196 {
197 InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
198 m_interestFilterTable.end(),
199 MatchInterestFilterId(interestFilterId));
200 if (i != m_interestFilterTable.end())
201 {
202 m_interestFilterTable.erase(i);
203 }
204 }
205
206 /////////////////////////////////////////////////////////////////////////////////////////////////
207 /////////////////////////////////////////////////////////////////////////////////////////////////
208
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700209 const RegisteredPrefixId*
210 registerPrefix(const Name& prefix,
211 const shared_ptr<InterestFilterRecord>& filter,
212 const RegisterPrefixSuccessCallback& onSuccess,
213 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700214 uint64_t flags,
Junxiao Shi388ec252014-11-02 15:19:57 -0700215 const nfd::CommandOptions& options)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700216 {
217 using namespace nfd;
218
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400219 ControlParameters params;
220 params.setName(prefix);
221 params.setFlags(flags);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700222
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400223 auto prefixToRegister = make_shared<RegisteredPrefix>(prefix, filter, options);
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700224
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400225 m_face.m_nfdController->start<RibRegisterCommand>(params,
226 bind(&Impl::afterPrefixRegistered, this,
227 prefixToRegister, onSuccess),
228 bind(onFailure, prefixToRegister->getPrefix(), _2),
229 options);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700230
231 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
232 }
233
234 void
235 afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
236 const RegisterPrefixSuccessCallback& onSuccess)
237 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800238 m_registeredPrefixTable.insert(registeredPrefix);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700239
240 if (static_cast<bool>(registeredPrefix->getFilter())) {
241 // it was a combined operation
242 m_interestFilterTable.push_back(registeredPrefix->getFilter());
243 }
244
245 if (static_cast<bool>(onSuccess)) {
246 onSuccess(registeredPrefix->getPrefix());
247 }
248 }
249
250 void
251 asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
252 const UnregisterPrefixSuccessCallback& onSuccess,
253 const UnregisterPrefixFailureCallback& onFailure)
254 {
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400255 using namespace nfd;
256 auto i = std::find_if(m_registeredPrefixTable.begin(),
257 m_registeredPrefixTable.end(),
258 MatchRegisteredPrefixId(registeredPrefixId));
259 if (i != m_registeredPrefixTable.end()) {
260 RegisteredPrefix& record = **i;
261
262 const shared_ptr<InterestFilterRecord>& filter = record.getFilter();
263
264 if (filter != nullptr) {
265 // it was a combined operation
266 m_interestFilterTable.remove(filter);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700267 }
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400268
269 ControlParameters params;
270 params.setName(record.getPrefix());
271 m_face.m_nfdController->start<RibUnregisterCommand>(params,
272 bind(&Impl::finalizeUnregisterPrefix, this, i, onSuccess),
273 bind(onFailure, _2),
274 record.getCommandOptions());
275 }
Alexander Afanasyev851228a2014-10-20 15:55:28 -0400276 else {
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400277 if (onFailure != nullptr) {
Alexander Afanasyev851228a2014-10-20 15:55:28 -0400278 onFailure("Unrecognized PrefixId");
279 }
280 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700281
282 // there cannot be two registered prefixes with the same id
283 }
284
285 void
286 finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
287 const UnregisterPrefixSuccessCallback& onSuccess)
288 {
289 m_registeredPrefixTable.erase(item);
290
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700291 if (static_cast<bool>(onSuccess)) {
292 onSuccess();
293 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700294 }
295
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700296private:
297 Face& m_face;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800298 util::Scheduler m_scheduler;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700299
300 PendingInterestTable m_pendingInterestTable;
301 InterestFilterTable m_interestFilterTable;
302 RegisteredPrefixTable m_registeredPrefixTable;
303
Alexander Afanasyeve9741322015-08-19 23:04:52 -0700304 shared_ptr<NfdFace> m_nfdFace;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700305
306 friend class Face;
307};
308
309} // namespace ndn
310
311#endif // NDN_DETAIL_FACE_IMPL_HPP