blob: d1047d347ac563baeb32e776af2426a97a4aae1b [file] [log] [blame]
shockjianga5ae48c2014-07-27 23:21:41 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California.
4 *
5 * This file is part of NDNS (Named Data Networking Domain Name Service).
6 * See AUTHORS.md for complete list of NDNS authors and contributors.
7 *
8 * NDNS is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef NAME_RESOLVER_HPP
20#define NAME_RESOLVER_HPP
21
22#include <boost/asio.hpp>
23#include <boost/noncopyable.hpp>
24
25#include <ndn-cxx/face.hpp>
26#include <ndn-cxx/name.hpp>
27#include <ndn-cxx/security/key-chain.hpp>
28
29#include "zone.hpp"
30#include "db/zone-mgr.hpp"
31#include "db/rr-mgr.hpp"
32#include "query.hpp"
33#include "response.hpp"
34#include "rr.hpp"
35#include "iterative-query.hpp"
shockjiang99ad3892014-08-03 14:56:13 -070036#include "iterative-query-with-forwarding-hint.hpp"
shockjianga5ae48c2014-07-27 23:21:41 -070037#include "ndn-app.hpp"
38
39using namespace std;
40
41namespace ndn {
42namespace ndns {
43
shockjiang99ad3892014-08-03 14:56:13 -070044template <class IQStrategy> //IQ stands for iterative Query Strategy
45class NameCachingResolver: public NDNApp
shockjianga5ae48c2014-07-27 23:21:41 -070046{
shockjianga5ae48c2014-07-27 23:21:41 -070047
48public:
49
shockjiang99ad3892014-08-03 14:56:13 -070050 NameCachingResolver(const char *programName, const char *prefix);
shockjianga5ae48c2014-07-27 23:21:41 -070051
shockjiang99ad3892014-08-03 14:56:13 -070052 void
53 resolve(IQStrategy& iq);
shockjianga5ae48c2014-07-27 23:21:41 -070054
shockjiang99ad3892014-08-03 14:56:13 -070055 using NDNApp::onData;
56 void
57 onData(const Interest& interest, Data &data, IQStrategy& iq);
shockjianga5ae48c2014-07-27 23:21:41 -070058
shockjiang99ad3892014-08-03 14:56:13 -070059 void
60 onInterest(const Name &name, const Interest &interest);
shockjianga5ae48c2014-07-27 23:21:41 -070061
shockjiang99ad3892014-08-03 14:56:13 -070062 using NDNApp::onTimeout;
63 void
64 onTimeout(const Interest& interest, IQStrategy& iq);
shockjianga5ae48c2014-07-27 23:21:41 -070065
shockjiang99ad3892014-08-03 14:56:13 -070066 void
67 run();
shockjianga5ae48c2014-07-27 23:21:41 -070068
shockjiang99ad3892014-08-03 14:56:13 -070069 const Name& getRootZoneFowardingHint() const
70 {
71 return m_rootZoneFowardingHint;
72 }
shockjianga5ae48c2014-07-27 23:21:41 -070073
shockjiang99ad3892014-08-03 14:56:13 -070074 void setRootZoneFowardingHint(const Name& rootZoneFowardingHint)
75 {
76 m_rootZoneFowardingHint = rootZoneFowardingHint;
77 }
shockjianga5ae48c2014-07-27 23:21:41 -070078
79private:
shockjiang99ad3892014-08-03 14:56:13 -070080 /**
81 * 0 means disable forwarding hint,
82 * 1 means enable forwarding hint
83 * todo: 2, retrieve name and hint of the name server as a optimization way
84 */
85
86 Name m_rootZoneFowardingHint;
shockjianga5ae48c2014-07-27 23:21:41 -070087
88};
89
shockjiang99ad3892014-08-03 14:56:13 -070090
91template <typename IQStrategy>
92NameCachingResolver<IQStrategy>::NameCachingResolver(const char *programName,
93 const char *prefix)
94 : NDNApp(programName, prefix)
95 , m_rootZoneFowardingHint("/")
96{
97 this->setInterestLifetime(time::milliseconds(2000));
98}
99
100template <class IQStrategy> void
101NameCachingResolver<IQStrategy>::run()
102{
103 boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
104 signalSet.async_wait(boost::bind(&NDNApp::signalHandler, this));
105 // boost::bind(&NdnTlvPingServer::signalHandler, this)
106
107 Name name(m_prefix);
108 name.append(Query::toString(Query::QUERY_DNS_R));
109
110 m_face.setInterestFilter(name,
111 bind(&NameCachingResolver::onInterest, this, _1, _2),
112 bind(&NDNApp::onRegisterFailed, this, _1, _2));
113
114 std::cout << "\n=== NDNS Resolver " << m_programName
115 << " with routeble prefix " << name.toUri() << " starts";
116
117 if (this->m_enableForwardingHint > 0) {
118 std::cout<<" & Root Zone ForwardingHint "<<this->m_rootZoneFowardingHint.toUri();
119 }
120 std::cout<<"==="<< std::endl;
121
122 try {
123 m_face.processEvents();
124 } catch (std::exception& e) {
125 std::cerr << "ERROR: " << e.what() << std::endl;
126 m_hasError = true;
127 m_ioService.stop();
128 }
129}
130template <class IQStrategy> void
131NameCachingResolver<IQStrategy>::onData(const Interest& interest, Data &data, IQStrategy& iq)
132{
133 /*
134 if (interest.getName() != iq.getLastInterest().getName()) {
135 std::cout << iq << std::endl;
136 std::cout << "waiting for " << iq.getLastInterest().getName().toUri()
137 << std::endl;
138 std::cout << "coming data " << data.getName().toUri() << std::endl;
139 return;
140 }*/
141
142 iq.doData(data);
143
144 if (iq.getStep() == IterativeQuery::AnswerStub) {
145 Data data = iq.getLastResponse().toData();
146 Name name = iq.getQuery().getAuthorityZone();
147 name.append(Query::toString(iq.getQuery().getQueryType()));
148 name.append(iq.getQuery().getRrLabel());
149 name.append(RR::toString(iq.getQuery().getRrType()));
150 name.appendVersion();
151 data.setName(name);
152 data.setFreshnessPeriod(iq.getLastResponse().getFreshness());
153
154 m_keyChain.sign(data);
155 m_face.put(data);
156 std::cout << "[* <- *] answer Response ("
157 << Response::toString(iq.getLastResponse().getResponseType())
158 << ") to stub:" << std::endl;
159 std::cout << iq.getLastResponse() << std::endl;
160 for (int i = 0; i < 15; i++) {
161 std::cout << "----";
162 }
163 std::cout << std::endl << std::endl;
164
165 //iq.setStep(IterativeQuery::FinishedSuccessfully);
166
167 } else if (iq.getStep() == IterativeQuery::NSQuery) {
168 resolve(iq);
169 } else if (iq.getStep() == IterativeQuery::RRQuery) {
170 resolve(iq);
171 } else if (iq.getStep() == IterativeQuery::Abort) {
172 return;
173 } else if (iq.getStep() == IterativeQuery::FHQuery) {
174 resolve(iq);
175 }
176 else {
177 std::cout << "let me see the current step="
178 << IterativeQuery::toString(iq.getStep()) << std::endl;
179 std::cout << iq;
180 std::cout<<std::endl;
181 }
182
183}
184
185template <class IQStrategy> void
186NameCachingResolver<IQStrategy>::onInterest(const Name &name, const Interest &interest)
187{
188 Query query;
189 query.fromInterest(interest);
190 std::cout << "[* -> *] receive Interest: " << interest.getName().toUri()
191 << std::endl;
192 if (query.getQueryType() == Query::QUERY_DNS) {
193 cout << m_programName << " is not in charge of Query_DNS" << endl;
194 }
195
196 IQStrategy iq(query);
197
198 if (this->m_enableForwardingHint == 0) {
199
200 } else if (this->m_enableForwardingHint > 0) {
201 //std::cout<<"--------------------create a Forwarding Hint"<<std::endl;
202 IterativeQueryWithFowardingHint& iqfh =dynamic_cast<IterativeQueryWithFowardingHint&>(iq);
203 iqfh.setForwardingHint(this->m_rootZoneFowardingHint);
204 iqfh.setLastForwardingHint(this->m_rootZoneFowardingHint);
205 }
206 resolve(iq);
207}
208
209template <class IQStrategy> void
210NameCachingResolver<IQStrategy>::onTimeout(const Interest& interest, IQStrategy& iq)
211{
212 std::cout << "[* !! *] timeout Interest " << interest.getName().toUri()
213 << " timeouts" << std::endl;
214
215 iq.doTimeout();
216}
217
218template <class IQStrategy>
219void NameCachingResolver<IQStrategy>::resolve(IQStrategy& iq)
220{
221
222 Interest interest = iq.toLatestInterest();
223
224 //must be set before express interest,since the call will back call iq
225 //if set after, then the iq in call of onData will return nothing
226 //be very careful here, as a new guy to c++
227
228 interest.setInterestLifetime(this->getInterestLifetime());
229 iq.setLastInterest(interest);
230 /*
231 if (this->m_enableForwardingHint > 0)
232 {
233 //iq = (IterativeQueryWithFowardingHint)iq;
234 iq = dynamic_cast<IterativeQueryWithFowardingHint>iq;
235 }
236 */
237 std::cout<<"lastInterest="<<iq.getLastInterest()<<std::endl;
238
239 try {
240 m_face.expressInterest(interest,
241 boost::bind(&NameCachingResolver::onData, this, _1, _2, iq),
242 boost::bind(&NameCachingResolver::onTimeout, this, _1, iq));
243 //boost::bind(&NameCachingResolver::onData, this, _1, _2, ndn::ref(iq)),
244 //boost::bind(&NameCachingResolver::onTimeout, this, _1, iq));
245 } catch (std::exception& e) {
246 std::cerr << "ERROR: " << e.what() << std::endl;
247 }
248
249 std::cout << "[* <- *] send Interest: " << interest.getName().toUri()
250 << std::endl;
251 std::cout << iq << std::endl;
252}
shockjianga5ae48c2014-07-27 23:21:41 -0700253} /* namespace ndns */
254} /* namespace ndn */
255
256#endif /* NAME_RESOLVER_HPP_ */