blob: 3c25505f7b52779bc280ec4013441538a93bbcfe [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{
66 NdnsType ndnsType = NDNS_RAW;
67 const Block* block = data.getMetaInfo().findAppMetaInfo(ndns::tlv::NdnsType);
68 if (block != nullptr) {
69 ndnsType = static_cast<NdnsType>(readNonNegativeInteger(*block));
70 }
71
72 NDNS_LOG_TRACE("[* -> *] get a " << ndnsType
73 << " Response: " << data.getName());
Shock Jiang5d5928c2014-12-03 13:41:22 -080074 if (m_validator == nullptr) {
75 this->onDataValidated(make_shared<Data>(data), ndnsType);
76 }
77 else {
78 m_validator->validate(data,
79 bind(&IterativeQueryController::onDataValidated, this, _1, ndnsType),
80 [this] (const shared_ptr<const Data>& data, const std::string& str) {
81 NDNS_LOG_WARN("data: " << data->getName() << " fails verification");
82 this->abort();
83 }
84 );
85 }
86}
87void
88IterativeQueryController::onDataValidated(const shared_ptr<const Data>& data, NdnsType ndnsType)
89{
Shock Jiang698e6ed2014-11-09 11:22:24 -080090 switch (m_step) {
91 case QUERY_STEP_QUERY_NS:
92 if (ndnsType == NDNS_NACK) {
Shock Jiang06cd2142014-11-23 17:36:02 -080093 m_step = QUERY_STEP_QUERY_RR;
Shock Jiang698e6ed2014-11-09 11:22:24 -080094 }
95 else if (ndnsType == NDNS_RESP) {
96 if (m_nFinishedComps + m_nTryComps == m_dstLabel.size() && m_rrType == label::NS_RR_TYPE) {
97 // NS_RR_TYPE is different, since its record is stored at higher level
98 m_step = QUERY_STEP_ANSWER_STUB;
99 }
100 else {
101 m_nFinishedComps += m_nTryComps;
102 m_nTryComps = 1;
103 }
104 }
105 else if (ndnsType == NDNS_AUTH) {
106 m_nTryComps += 1;
107 }
108 else if (ndnsType == NDNS_RAW) {
109 std::ostringstream oss;
110 oss << *this;
111 NDNS_LOG_WARN("get unexpected Response: NDNS_RAW for QUERY_NS: " << oss.str());
112 }
113 //
114 if (m_nFinishedComps + m_nTryComps > m_dstLabel.size()) {
115 if (m_rrType == label::NS_RR_TYPE) {
116 m_step = QUERY_STEP_ANSWER_STUB;
117 }
118 else
119 m_step = QUERY_STEP_QUERY_RR;
120 }
121 break;
122 case QUERY_STEP_QUERY_RR:
123 m_step = QUERY_STEP_ANSWER_STUB;
124 break;
125 default:
126 NDNS_LOG_WARN("get unexpected Response at State " << *this);
127 // throw std::runtime_error("call makeLatestInterest() unexpected: " << *this);
128 // do not throw except since it may be duplicated Data
129 m_step = QUERY_STEP_ABORT;
130 break;
131 }
132
133 if (!hasEnded())
134 this->express(this->makeLatestInterest()); // express new Expres
135 else if (m_step == QUERY_STEP_ANSWER_STUB) {
136 NDNS_LOG_TRACE("query ends: " << *this);
Shock Jiang5d5928c2014-12-03 13:41:22 -0800137 Response re = this->parseFinalResponse(*data);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800138 if (m_onSucceed != nullptr)
Shock Jiang5d5928c2014-12-03 13:41:22 -0800139 m_onSucceed(*data, re);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800140 else
141 NDNS_LOG_TRACE("succeed callback is nullptr");
142 }
143 else if (m_step == QUERY_STEP_ABORT)
144 this->abort();
145}
146
147bool
148IterativeQueryController::hasEnded()
149{
150 return (m_step != QUERY_STEP_QUERY_NS && m_step != QUERY_STEP_QUERY_RR);
151}
152
153void
154IterativeQueryController::start()
155{
Shock Jiang5d5928c2014-12-03 13:41:22 -0800156 if (m_dstLabel.size() == m_nFinishedComps)
157 m_step = QUERY_STEP_QUERY_RR;
158
Shock Jiang698e6ed2014-11-09 11:22:24 -0800159 Interest interest = this->makeLatestInterest();
160 express(interest);
161}
162
163
164void
165IterativeQueryController::express(const Interest& interest)
166{
167 NDNS_LOG_DEBUG("[* <- *] send a Query: " << interest.getName());
168 m_face.expressInterest(interest,
169 bind(&IterativeQueryController::onData, this, _1, _2),
170 bind(&IterativeQueryController::onTimeout, this, _1)
171 );
172}
173
174
175const Response
176IterativeQueryController::parseFinalResponse(const Data& data)
177{
178 Response re;
179 Name zone = m_dstLabel.getPrefix(m_nFinishedComps);
Yumin Xia6343c5b2016-10-20 15:45:50 -0700180 re.fromData(zone, data);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800181 return re;
182}
183
184const Interest
185IterativeQueryController::makeLatestInterest()
186{
187 // NDNS_LOG_TRACE("get latest Interest");
188 Query query;
189 //const Name& dstLabel = m_query.getRrLabel();
190
191 query.setZone(m_dstLabel.getPrefix(m_nFinishedComps));
192 query.setInterestLifetime(m_interestLifetime);
193 switch (m_step) {
194 case QUERY_STEP_QUERY_NS:
195 query.setQueryType(label::NDNS_ITERATIVE_QUERY);
196 query.setRrLabel(m_dstLabel.getSubName(m_nFinishedComps, m_nTryComps));
197 query.setRrType(label::NS_RR_TYPE);
198 break;
199 case QUERY_STEP_QUERY_RR:
200 if (m_rrType == label::CERT_RR_TYPE) {
201 // this only works for dsk, and ksk needs different mechanism
202 query.setQueryType(label::NDNS_CERT_QUERY);
203 }
204 else {
205 query.setQueryType(label::NDNS_ITERATIVE_QUERY);
206 }
207 query.setRrLabel(m_dstLabel.getSubName(m_nFinishedComps));
208 query.setRrType(m_rrType);
209 break;
210 default:
211 std::ostringstream oss;
212 oss << *this;
213 NDNS_LOG_WARN("unexpected state: " << oss.str());
214 throw std::runtime_error("call makeLatestInterest() unexpected: " + oss.str());
215 }
216
217
218 Interest interest = query.toInterest();
219 return interest;
220}
221
222std::ostream&
223operator<<(std::ostream& os, const IterativeQueryController::QueryStep step)
224{
225 switch (step) {
226 case IterativeQueryController::QUERY_STEP_QUERY_NS:
227 os << "QueryNS";
228 break;
229 case IterativeQueryController::QUERY_STEP_QUERY_RR:
230 os << "QueryRR";
231 break;
232 case IterativeQueryController::QUERY_STEP_ANSWER_STUB:
233 os << "AnswerStub";
234 break;
235 case IterativeQueryController::QUERY_STEP_ABORT:
236 os << "Abort";
237 break;
238 default:
239 os << "UNKNOW";
240 break;
241 }
242 return os;
243}
244
245std::ostream&
246operator<<(std::ostream& os, const IterativeQueryController& ctr)
247{
248 os << "InterativeQueryController: dstLabel=" << ctr.getDstLabel()
249 << " rrType=" << ctr.getRrType()
250 << " currentStep=" << ctr.getStep()
251 << " nFinishedComps=" << ctr.getNFinishedComps()
252 << " nTryComp=" << ctr.getNTryComps()
253 ;
254
255 return os;
256}
257
258} // namespace ndns
259} // namespace ndn