blob: 5a143a5d83f52545ead3de2181aee90bedf45fa8 [file] [log] [blame]
Shock Jiang698e6ed2014-11-09 11:22:24 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yumin Xia6343c5b2016-10-20 15:45:50 -07003 * Copyright (c) 2014-2016, Regents of the University of California.
Shock Jiang698e6ed2014-11-09 11:22:24 -08004 *
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
Shock Jiang5d5928c2014-12-03 13:41:22 -080020#include "validator.hpp"
Shock Jiang698e6ed2014-11-09 11:22:24 -080021#include "iterative-query-controller.hpp"
22#include "logger.hpp"
23#include <iostream>
24
25namespace ndn {
26namespace ndns {
27NDNS_LOG_INIT("IterQueryCtr")
28
29IterativeQueryController::IterativeQueryController(const Name& dstLabel,
30 const name::Component& rrType,
31 const time::milliseconds& interestLifetime,
32 const QuerySucceedCallback& onSucceed,
33 const QueryFailCallback& onFail,
Shock Jiang5d5928c2014-12-03 13:41:22 -080034 Face& face,
35 Validator* validator)
Shock Jiang698e6ed2014-11-09 11:22:24 -080036 : QueryController(dstLabel, rrType, interestLifetime, onSucceed, onFail, face)
Shock Jiang5d5928c2014-12-03 13:41:22 -080037 , m_validator(validator)
Shock Jiang698e6ed2014-11-09 11:22:24 -080038 , m_step(QUERY_STEP_QUERY_NS)
39 , m_nFinishedComps(0)
40 , m_nTryComps(1)
41{
Shock Jiang698e6ed2014-11-09 11:22:24 -080042}
43
44void
45IterativeQueryController::onTimeout(const Interest& interest)
46{
47 NDNS_LOG_INFO("[* !! *] timeout happens: " << interest.getName());
48 NDNS_LOG_TRACE(*this);
49 this->abort();
50}
51
52void
53IterativeQueryController::abort()
54{
55 NDNS_LOG_DEBUG("abort iterative query");
56 if (m_onFail != nullptr)
57 m_onFail(0, "abort");
58 else
59 NDNS_LOG_TRACE("m_onFail is 0");
60
61}
62
63void
64IterativeQueryController::onData(const ndn::Interest& interest, const Data& data)
65{
Yumin Xiaa484ba72016-11-10 20:40:12 -080066 NdnsContentType contentType = NdnsContentType(data.getContentType());
Shock Jiang698e6ed2014-11-09 11:22:24 -080067
Yumin Xiaa484ba72016-11-10 20:40:12 -080068 NDNS_LOG_TRACE("[* -> *] get a " << contentType
Shock Jiang698e6ed2014-11-09 11:22:24 -080069 << " Response: " << data.getName());
Shock Jiang5d5928c2014-12-03 13:41:22 -080070 if (m_validator == nullptr) {
Yumin Xiaa484ba72016-11-10 20:40:12 -080071 this->onDataValidated(make_shared<Data>(data), contentType);
Shock Jiang5d5928c2014-12-03 13:41:22 -080072 }
73 else {
74 m_validator->validate(data,
Yumin Xiaa484ba72016-11-10 20:40:12 -080075 bind(&IterativeQueryController::onDataValidated, this, _1, contentType),
Shock Jiang5d5928c2014-12-03 13:41:22 -080076 [this] (const shared_ptr<const Data>& data, const std::string& str) {
77 NDNS_LOG_WARN("data: " << data->getName() << " fails verification");
78 this->abort();
79 }
80 );
81 }
82}
83void
Yumin Xiaa484ba72016-11-10 20:40:12 -080084IterativeQueryController::onDataValidated(const shared_ptr<const Data>& data, NdnsContentType contentType)
Shock Jiang5d5928c2014-12-03 13:41:22 -080085{
Shock Jiang698e6ed2014-11-09 11:22:24 -080086 switch (m_step) {
87 case QUERY_STEP_QUERY_NS:
Yumin Xiaa484ba72016-11-10 20:40:12 -080088 if (contentType == NDNS_NACK) {
Shock Jiang06cd2142014-11-23 17:36:02 -080089 m_step = QUERY_STEP_QUERY_RR;
Shock Jiang698e6ed2014-11-09 11:22:24 -080090 }
Yumin Xiaa484ba72016-11-10 20:40:12 -080091 else if (contentType == NDNS_LINK) {
92 Link link(data->wireEncode());
93 if (link.getDelegations().empty()) {
94 m_lastLink = Block();
95 } else {
96 m_lastLink = data->wireEncode();
Yumin Xia4e561892016-10-21 10:48:01 -070097 }
Yumin Xiaa484ba72016-11-10 20:40:12 -080098
99 // for NS query, if already received, just return, instead of more queries until NACK
Shock Jiang698e6ed2014-11-09 11:22:24 -0800100 if (m_nFinishedComps + m_nTryComps == m_dstLabel.size() && m_rrType == label::NS_RR_TYPE) {
101 // NS_RR_TYPE is different, since its record is stored at higher level
102 m_step = QUERY_STEP_ANSWER_STUB;
103 }
104 else {
105 m_nFinishedComps += m_nTryComps;
106 m_nTryComps = 1;
107 }
108 }
Yumin Xiaa484ba72016-11-10 20:40:12 -0800109 else if (contentType == NDNS_AUTH) {
Shock Jiang698e6ed2014-11-09 11:22:24 -0800110 m_nTryComps += 1;
111 }
Yumin Xiaa484ba72016-11-10 20:40:12 -0800112 else if (contentType == NDNS_BLOB) {
Shock Jiang698e6ed2014-11-09 11:22:24 -0800113 std::ostringstream oss;
114 oss << *this;
Yumin Xiaa484ba72016-11-10 20:40:12 -0800115 NDNS_LOG_WARN("get unexpected Response: NDNS_BLOB for QUERY_NS: " << oss.str());
116 } else {
117 std::ostringstream oss;
118 oss << *this;
119 NDNS_LOG_WARN("get unexpected Response for QUERY_NS: " << oss.str());
Shock Jiang698e6ed2014-11-09 11:22:24 -0800120 }
121 //
122 if (m_nFinishedComps + m_nTryComps > m_dstLabel.size()) {
123 if (m_rrType == label::NS_RR_TYPE) {
124 m_step = QUERY_STEP_ANSWER_STUB;
125 }
126 else
127 m_step = QUERY_STEP_QUERY_RR;
128 }
129 break;
130 case QUERY_STEP_QUERY_RR:
131 m_step = QUERY_STEP_ANSWER_STUB;
132 break;
133 default:
134 NDNS_LOG_WARN("get unexpected Response at State " << *this);
135 // throw std::runtime_error("call makeLatestInterest() unexpected: " << *this);
136 // do not throw except since it may be duplicated Data
137 m_step = QUERY_STEP_ABORT;
138 break;
139 }
140
141 if (!hasEnded())
142 this->express(this->makeLatestInterest()); // express new Expres
143 else if (m_step == QUERY_STEP_ANSWER_STUB) {
144 NDNS_LOG_TRACE("query ends: " << *this);
Shock Jiang5d5928c2014-12-03 13:41:22 -0800145 Response re = this->parseFinalResponse(*data);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800146 if (m_onSucceed != nullptr)
Shock Jiang5d5928c2014-12-03 13:41:22 -0800147 m_onSucceed(*data, re);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800148 else
149 NDNS_LOG_TRACE("succeed callback is nullptr");
150 }
151 else if (m_step == QUERY_STEP_ABORT)
152 this->abort();
153}
154
155bool
156IterativeQueryController::hasEnded()
157{
158 return (m_step != QUERY_STEP_QUERY_NS && m_step != QUERY_STEP_QUERY_RR);
159}
160
161void
162IterativeQueryController::start()
163{
Shock Jiang5d5928c2014-12-03 13:41:22 -0800164 if (m_dstLabel.size() == m_nFinishedComps)
165 m_step = QUERY_STEP_QUERY_RR;
166
Shock Jiang698e6ed2014-11-09 11:22:24 -0800167 Interest interest = this->makeLatestInterest();
168 express(interest);
169}
170
171
172void
173IterativeQueryController::express(const Interest& interest)
174{
175 NDNS_LOG_DEBUG("[* <- *] send a Query: " << interest.getName());
176 m_face.expressInterest(interest,
177 bind(&IterativeQueryController::onData, this, _1, _2),
Alexander Afanasyevf4193ea2017-06-12 15:35:13 -0700178 bind(&IterativeQueryController::onTimeout, this, _1), // nack
Shock Jiang698e6ed2014-11-09 11:22:24 -0800179 bind(&IterativeQueryController::onTimeout, this, _1)
180 );
181}
182
183
184const Response
185IterativeQueryController::parseFinalResponse(const Data& data)
186{
187 Response re;
188 Name zone = m_dstLabel.getPrefix(m_nFinishedComps);
Yumin Xia6343c5b2016-10-20 15:45:50 -0700189 re.fromData(zone, data);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800190 return re;
191}
192
193const Interest
194IterativeQueryController::makeLatestInterest()
195{
196 // NDNS_LOG_TRACE("get latest Interest");
197 Query query;
198 //const Name& dstLabel = m_query.getRrLabel();
199
200 query.setZone(m_dstLabel.getPrefix(m_nFinishedComps));
201 query.setInterestLifetime(m_interestLifetime);
Yumin Xia4e561892016-10-21 10:48:01 -0700202
203 // addLink
204 if (m_lastLink.hasWire()) {
205 query.setLink(m_lastLink);
206 }
207
Shock Jiang698e6ed2014-11-09 11:22:24 -0800208 switch (m_step) {
209 case QUERY_STEP_QUERY_NS:
210 query.setQueryType(label::NDNS_ITERATIVE_QUERY);
211 query.setRrLabel(m_dstLabel.getSubName(m_nFinishedComps, m_nTryComps));
212 query.setRrType(label::NS_RR_TYPE);
213 break;
214 case QUERY_STEP_QUERY_RR:
215 if (m_rrType == label::CERT_RR_TYPE) {
216 // this only works for dsk, and ksk needs different mechanism
217 query.setQueryType(label::NDNS_CERT_QUERY);
218 }
219 else {
220 query.setQueryType(label::NDNS_ITERATIVE_QUERY);
221 }
222 query.setRrLabel(m_dstLabel.getSubName(m_nFinishedComps));
223 query.setRrType(m_rrType);
224 break;
225 default:
226 std::ostringstream oss;
227 oss << *this;
228 NDNS_LOG_WARN("unexpected state: " << oss.str());
229 throw std::runtime_error("call makeLatestInterest() unexpected: " + oss.str());
230 }
231
Shock Jiang698e6ed2014-11-09 11:22:24 -0800232 Interest interest = query.toInterest();
233 return interest;
234}
235
236std::ostream&
237operator<<(std::ostream& os, const IterativeQueryController::QueryStep step)
238{
239 switch (step) {
240 case IterativeQueryController::QUERY_STEP_QUERY_NS:
241 os << "QueryNS";
242 break;
243 case IterativeQueryController::QUERY_STEP_QUERY_RR:
244 os << "QueryRR";
245 break;
246 case IterativeQueryController::QUERY_STEP_ANSWER_STUB:
247 os << "AnswerStub";
248 break;
249 case IterativeQueryController::QUERY_STEP_ABORT:
250 os << "Abort";
251 break;
252 default:
253 os << "UNKNOW";
254 break;
255 }
256 return os;
257}
258
259std::ostream&
260operator<<(std::ostream& os, const IterativeQueryController& ctr)
261{
262 os << "InterativeQueryController: dstLabel=" << ctr.getDstLabel()
263 << " rrType=" << ctr.getRrType()
264 << " currentStep=" << ctr.getStep()
265 << " nFinishedComps=" << ctr.getNFinishedComps()
266 << " nTryComp=" << ctr.getNTryComps()
267 ;
268
269 return os;
270}
271
272} // namespace ndns
273} // namespace ndn