blob: 18142a09883f5fa25d3257f9d6d40edb7f7b016e [file] [log] [blame]
Shock Jiang698e6ed2014-11-09 11:22:24 -08001/* -*- 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
20#include "ndns-label.hpp"
21#include "logger.hpp"
22#include "clients/response.hpp"
23#include "clients/query.hpp"
24#include "clients/iterative-query-controller.hpp"
25#include "validator.hpp"
Shock Jiang06cd2142014-11-23 17:36:02 -080026#include "util/util.hpp"
Shock Jiang698e6ed2014-11-09 11:22:24 -080027
28#include <ndn-cxx/security/key-chain.hpp>
29#include <ndn-cxx/face.hpp>
30#include <boost/program_options.hpp>
31#include <boost/asio.hpp>
32#include <boost/filesystem.hpp>
33#include <boost/noncopyable.hpp>
34
35#include <memory>
36#include <string>
37
Shock Jiang698e6ed2014-11-09 11:22:24 -080038namespace ndn {
39namespace ndns {
40NDNS_LOG_INIT("NdnsDig");
41
42class NdnsDig
43{
44public:
45 NdnsDig(const Name& hint, const Name& dstLabel,
46 const name::Component& rrType)
47 : m_dstLabel(dstLabel)
48 , m_rrType(rrType)
49 , m_hint(hint)
50 , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
51 , m_validator(m_face)
52 , m_ctr(new IterativeQueryController(m_dstLabel, m_rrType, m_interestLifetime,
53 bind(&NdnsDig::onSucceed, this, _1, _2),
54 bind(&NdnsDig::onFail, this, _1, _2),
55 m_face))
56 , m_hasError(false)
57 {
58 }
59
60 void
61 run()
62 {
63 NDNS_LOG_INFO(" =================================== "
64 << "start to dig label = " << this->m_dstLabel
65 << " for type = " << this->m_rrType
66 << " =================================== ");
67
68 try {
69 m_ctr->start(); // non-block, may throw exception
70 m_face.processEvents();
71 }
72 catch (std::exception& e) {
73 NDNS_LOG_FATAL("Error: Face fails to process events: " << e.what());
74 m_hasError = true;
75 }
76 }
77
78 void
79 stop()
80 {
81 m_face.getIoService().stop();
82 NDNS_LOG_TRACE("application stops.");
83 }
84
85private:
86 void
87 onSucceed(const Data& data, const Response& response)
88 {
Shock Jiang06cd2142014-11-23 17:36:02 -080089 NDNS_LOG_INFO("Dig get following Response (need verification):");
90 Name name = Name().append(response.getZone()).append(response.getRrLabel());
91 if (name == m_dstLabel && m_rrType == response.getRrType()) {
92 NDNS_LOG_INFO("This is the final response returned by zone=" << response.getZone()
93 << " and NdnsType=" << response.getNdnsType()
94 << ". It contains " << response.getRrs().size() << " RR(s)");
95
96 std::string msg;
97 size_t i = 0;
98 for (const auto& rr : response.getRrs()) {
99 try {
100 msg = std::string(reinterpret_cast<const char*>(rr.value()), rr.value_size());
101 NDNS_LOG_INFO("succeed to get the info from RR[" << i << "]"
102 "type=" << rr.type() << " content=" << msg);
103 }
104 catch (std::exception& e) {
105 NDNS_LOG_INFO("error to get the info from RR[" << i << "]"
106 "type=" << rr.type());
107 }
108 ++i;
109 }
110 }
111 else {
112 NDNS_LOG_INFO("[* !! *] This is not final response.The target Label: "
113 << m_dstLabel << " may not exist");
114 }
115
116 if (m_dstFile.empty()) {
117 ;
118 }
119 else if (m_dstFile == "-") {
120 output(data, std::cout, true);
121 }
122 else {
123 NDNS_LOG_INFO("output Data packet to " << m_dstFile << " with BASE64 encoding format");
124 std::filebuf fb;
125 fb.open(m_dstFile, std::ios::out);
126 std::ostream os(&fb);
127 output(data, os, false);
128 }
129
Shock Jiang698e6ed2014-11-09 11:22:24 -0800130 NDNS_LOG_INFO(response);
Shock Jiang06cd2142014-11-23 17:36:02 -0800131
Shock Jiang698e6ed2014-11-09 11:22:24 -0800132 NDNS_LOG_TRACE("to verify the response");
133 m_validator.validate(data,
134 bind(&NdnsDig::onDataValidated, this, _1),
135 bind(&NdnsDig::onDataValidationFailed, this, _1, _2)
136 );
137 }
138
Shock Jiang06cd2142014-11-23 17:36:02 -0800139
Shock Jiang698e6ed2014-11-09 11:22:24 -0800140 void
141 onFail(uint32_t errCode, const std::string& errMsg)
142 {
143 NDNS_LOG_INFO("fail to get response: errCode=" << errCode << " msg=" << errMsg);
144 m_hasError = true;
145 this->stop();
146 }
147
148 void
149 onDataValidated(const shared_ptr<const Data>& data)
150 {
151 NDNS_LOG_INFO("final data pass verification");
152 this->stop();
153 }
154
155 void
156 onDataValidationFailed(const shared_ptr<const Data>& data, const std::string& str)
157 {
158 NDNS_LOG_INFO("final data does not pass verification");
159 m_hasError = true;
160 this->stop();
161 }
162
163public:
164 void
165 setInterestLifetime(const time::milliseconds& lifetime)
166 {
167 m_interestLifetime = lifetime;
168 }
169
170 const bool
171 hasError() const
172 {
173 return m_hasError;
174 }
175
Shock Jiang06cd2142014-11-23 17:36:02 -0800176 void
177 setDstFile(const std::string& dstFile)
178 {
179 m_dstFile = dstFile;
180 }
181
Shock Jiang698e6ed2014-11-09 11:22:24 -0800182private:
183 Name m_dstLabel;
184 name::Component m_rrType;
185
186 Name m_hint;
187 Name m_certName;
188 time::milliseconds m_interestLifetime;
189
190 Face m_face;
191
192 Validator m_validator;
193 std::unique_ptr<QueryController> m_ctr;
194
195 bool m_hasError;
Shock Jiang06cd2142014-11-23 17:36:02 -0800196 std::string m_dstFile;
Shock Jiang698e6ed2014-11-09 11:22:24 -0800197};
198
199} // namespace ndns
200} // namespace ndn
201
202
203int
204main(int argc, char* argv[])
205{
206 ndn::ndns::log::init();
207 using std::string;
208 using namespace ndn;
209
210 Name dstLabel;
211 int ttl = 4;
212 string rrType = "TXT";
Shock Jiang06cd2142014-11-23 17:36:02 -0800213 string dstFile;
Shock Jiang698e6ed2014-11-09 11:22:24 -0800214 try {
215 namespace po = boost::program_options;
216 po::variables_map vm;
217
218 po::options_description generic("Generic Options");
219 generic.add_options()("help,h", "print help message");
220
221 po::options_description config("Configuration");
222 config.add_options()
Shock Jiang06cd2142014-11-23 17:36:02 -0800223 ("timeout,T", po::value<int>(&ttl), "waiting seconds of query. default: 4 sec")
Shock Jiang698e6ed2014-11-09 11:22:24 -0800224 ("rrtype,t", po::value<std::string>(&rrType), "set request RR Type. default: TXT")
Shock Jiang06cd2142014-11-23 17:36:02 -0800225 ("dstFile,d", po::value<std::string>(&dstFile), "set output file of the received Data. "
226 "if omitted, not print; if set to be -, print to stdout; else print to file")
Shock Jiang698e6ed2014-11-09 11:22:24 -0800227 ;
228
229 po::options_description hidden("Hidden Options");
230 hidden.add_options()
231 ("name", po::value<Name>(&dstLabel), "name to be resolved")
232 ;
233 po::positional_options_description postion;
234 postion.add("name", 1);
235
236 po::options_description cmdline_options;
237 cmdline_options.add(generic).add(config).add(hidden);
238
239 po::options_description config_file_options;
240 config_file_options.add(config).add(hidden);
241
Shock Jiang06cd2142014-11-23 17:36:02 -0800242 po::options_description visible("Usage: ndns-dig /name/to/be/resolved [-t rrType] [-T ttl]"
243 "[-d dstFile]\n"
244 "Allowed options");
245
Shock Jiang698e6ed2014-11-09 11:22:24 -0800246 visible.add(generic).add(config);
247
248 po::parsed_options parsed =
249 po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
250
251 po::store(parsed, vm);
252 po::notify(vm);
253
254 if (vm.count("help")) {
Shock Jiang698e6ed2014-11-09 11:22:24 -0800255 std::cout << visible << std::endl;
256 return 0;
257 }
258 }
259 catch (const std::exception& ex) {
260 std::cerr << "Parameter Error: " << ex.what() << std::endl;
261 return 0;
262 }
263
264 ndn::ndns::NdnsDig dig("", dstLabel, ndn::name::Component(rrType));
265 dig.setInterestLifetime(ndn::time::milliseconds(ttl * 1000));
Shock Jiang06cd2142014-11-23 17:36:02 -0800266 dig.setDstFile(dstFile);
Shock Jiang698e6ed2014-11-09 11:22:24 -0800267
268 dig.run();
269 if (dig.hasError())
270 return 1;
271 else
272 return 0;
273}