blob: d43f1d288363afa1f77395d085976ff62743bdba [file] [log] [blame]
Eric Newberry94996d62015-05-07 13:48:46 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento5923bf82018-08-09 01:55:44 -04002/*
Davide Pesaventoa0e6b602021-01-21 19:47:04 -05003 * Copyright (c) 2015-2021, Arizona Board of Regents.
Eric Newberry94996d62015-05-07 13:48:46 -07004 *
5 * This file is part of ndn-tools (Named Data Networking Essential Tools).
6 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
7 *
8 * ndn-tools 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 * ndn-tools 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 * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Eric Newberry <enewberry@email.arizona.edu>
20 * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
21 */
22
23#include "core/common.hpp"
24#include "core/version.hpp"
25
26#include "ping-server.hpp"
27#include "tracer.hpp"
28
Davide Pesaventoa0e6b602021-01-21 19:47:04 -050029#include <boost/asio/signal_set.hpp>
30#include <boost/program_options/options_description.hpp>
31#include <boost/program_options/parsers.hpp>
32#include <boost/program_options/variables_map.hpp>
33
Eric Newberry94996d62015-05-07 13:48:46 -070034namespace ndn {
35namespace ping {
36namespace server {
37
Davide Pesavento5923bf82018-08-09 01:55:44 -040038namespace po = boost::program_options;
39
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070040class Runner : noncopyable
41{
42public:
43 explicit
44 Runner(const Options& options)
45 : m_options(options)
46 , m_pingServer(m_face, m_keyChain, options)
47 , m_tracer(m_pingServer, options)
Davide Pesavento5923bf82018-08-09 01:55:44 -040048 , m_signalSet(m_face.getIoService(), SIGINT)
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070049 {
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070050 m_pingServer.afterFinish.connect([this] {
Davide Pesavento5923bf82018-08-09 01:55:44 -040051 m_pingServer.stop();
52 m_signalSet.cancel();
53 });
54
55 m_signalSet.async_wait([this] (const auto& ec, auto) {
56 if (ec != boost::asio::error::operation_aborted) {
57 m_pingServer.stop();
58 }
59 });
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070060 }
61
62 int
63 run()
64 {
Davide Pesavento5923bf82018-08-09 01:55:44 -040065 std::cout << "PING SERVER " << m_options.prefix << std::endl;
66
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070067 try {
68 m_pingServer.start();
69 m_face.processEvents();
70 }
Davide Pesavento5923bf82018-08-09 01:55:44 -040071 catch (const std::exception& e) {
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070072 std::cerr << "ERROR: " << e.what() << std::endl;
73 return 1;
74 }
75
Davide Pesavento5923bf82018-08-09 01:55:44 -040076 std::cout << "\n--- " << m_options.prefix << " ping server statistics ---\n"
77 << m_pingServer.getNPings() << " packets processed" << std::endl;
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070078 return 0;
79 }
80
81private:
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070082 const Options& m_options;
Davide Pesavento5923bf82018-08-09 01:55:44 -040083
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070084 Face m_face;
85 KeyChain m_keyChain;
86 PingServer m_pingServer;
87 Tracer m_tracer;
88
Davide Pesavento5923bf82018-08-09 01:55:44 -040089 boost::asio::signal_set m_signalSet;
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -070090};
91
Eric Newberry94996d62015-05-07 13:48:46 -070092static void
Davide Pesavento5923bf82018-08-09 01:55:44 -040093usage(std::ostream& os, const std::string& programName, const po::options_description& options)
Eric Newberry94996d62015-05-07 13:48:46 -070094{
Davide Pesavento5923bf82018-08-09 01:55:44 -040095 os << "Usage: " << programName << " [options] <prefix>\n"
96 << "\n"
97 << "Starts a NDN ping server that responds to Interests under name ndn:<prefix>/ping\n"
98 << "\n"
99 << options;
Eric Newberry94996d62015-05-07 13:48:46 -0700100}
101
Davide Pesavento5923bf82018-08-09 01:55:44 -0400102static int
Eric Newberry94996d62015-05-07 13:48:46 -0700103main(int argc, char* argv[])
104{
105 Options options;
Davide Pesavento5923bf82018-08-09 01:55:44 -0400106 std::string prefix;
107 auto nMaxPings = static_cast<std::make_signed_t<size_t>>(options.nMaxPings);
108 auto payloadSize = static_cast<std::make_signed_t<size_t>>(options.payloadSize);
Eric Newberry94996d62015-05-07 13:48:46 -0700109
Davide Pesavento5923bf82018-08-09 01:55:44 -0400110 po::options_description visibleDesc("Options");
111 visibleDesc.add_options()
112 ("help,h", "print this help message and exit")
Davide Pesavento0d4b1822019-07-27 19:32:05 -0400113 ("freshness,f", po::value<time::milliseconds::rep>()->default_value(options.freshnessPeriod.count()),
Davide Pesavento5923bf82018-08-09 01:55:44 -0400114 "FreshnessPeriod of the ping response, in milliseconds")
115 ("satisfy,p", po::value(&nMaxPings)->default_value(nMaxPings),
Davide Pesavento0d4b1822019-07-27 19:32:05 -0400116 "maximum number of pings to satisfy (0 = no limit)")
Davide Pesavento5923bf82018-08-09 01:55:44 -0400117 ("size,s", po::value(&payloadSize)->default_value(payloadSize),
118 "size of response payload")
Davide Pesavento2bdda1d2018-08-09 19:35:49 -0400119 ("timestamp,t", po::bool_switch(&options.wantTimestamp),
120 "prepend a timestamp to each log message")
121 ("quiet,q", po::bool_switch(&options.wantQuiet),
122 "do not print a log message each time a ping packet is received")
Davide Pesavento5923bf82018-08-09 01:55:44 -0400123 ("version,V", "print program version and exit")
124 ;
Eric Newberry94996d62015-05-07 13:48:46 -0700125
Davide Pesavento5923bf82018-08-09 01:55:44 -0400126 po::options_description hiddenDesc;
127 hiddenDesc.add_options()
128 ("prefix", po::value<std::string>(&prefix));
Eric Newberry94996d62015-05-07 13:48:46 -0700129
Davide Pesavento0d4b1822019-07-27 19:32:05 -0400130 po::options_description deprecatedDesc;
131 deprecatedDesc.add_options()
132 ("_deprecated_freshness_,x", po::value<time::milliseconds::rep>())
133 ;
Eric Newberry94996d62015-05-07 13:48:46 -0700134
Davide Pesavento5923bf82018-08-09 01:55:44 -0400135 po::options_description optDesc;
Davide Pesavento0d4b1822019-07-27 19:32:05 -0400136 optDesc.add(visibleDesc).add(hiddenDesc).add(deprecatedDesc);
137
138 po::positional_options_description posDesc;
139 posDesc.add("prefix", -1);
Davide Pesavento5923bf82018-08-09 01:55:44 -0400140
141 po::variables_map vm;
Eric Newberry94996d62015-05-07 13:48:46 -0700142 try {
Davide Pesavento5923bf82018-08-09 01:55:44 -0400143 po::store(po::command_line_parser(argc, argv).options(optDesc).positional(posDesc).run(), vm);
144 po::notify(vm);
Eric Newberry94996d62015-05-07 13:48:46 -0700145 }
146 catch (const po::error& e) {
Davide Pesavento5923bf82018-08-09 01:55:44 -0400147 std::cerr << "ERROR: " << e.what() << "\n\n";
148 usage(std::cerr, argv[0], visibleDesc);
149 return 2;
150 }
151 catch (const boost::bad_any_cast& e) {
152 std::cerr << "ERROR: " << e.what() << "\n\n";
153 usage(std::cerr, argv[0], visibleDesc);
154 return 2;
Eric Newberry94996d62015-05-07 13:48:46 -0700155 }
156
Davide Pesavento0d4b1822019-07-27 19:32:05 -0400157 if (vm.count("_deprecated_freshness_") > 0) {
158 std::cerr << "WARNING: short option '-x' is deprecated and will be removed in the near "
159 "future. Please use '-f' or the long form '--freshness'." << std::endl;
160 }
161
Davide Pesavento5923bf82018-08-09 01:55:44 -0400162 if (vm.count("help") > 0) {
163 usage(std::cout, argv[0], visibleDesc);
164 return 0;
165 }
166
167 if (vm.count("version") > 0) {
168 std::cout << "ndnpingserver " << tools::VERSION << std::endl;
169 return 0;
170 }
171
172 if (prefix.empty()) {
173 std::cerr << "ERROR: no name prefix specified\n\n";
174 usage(std::cerr, argv[0], visibleDesc);
175 return 2;
176 }
177 options.prefix = prefix;
178
179 options.freshnessPeriod = time::milliseconds(vm["freshness"].as<time::milliseconds::rep>());
Davide Pesavento0d4b1822019-07-27 19:32:05 -0400180 if (vm.count("_deprecated_freshness_") > 0) {
181 options.freshnessPeriod = time::milliseconds(vm["_deprecated_freshness_"].as<time::milliseconds::rep>());
182 }
Davide Pesavento5923bf82018-08-09 01:55:44 -0400183 if (options.freshnessPeriod < 0_ms) {
184 std::cerr << "ERROR: FreshnessPeriod cannot be negative" << std::endl;
185 return 2;
186 }
187
188 if (nMaxPings < 0) {
189 std::cerr << "ERROR: maximum number of pings to satisfy cannot be negative" << std::endl;
190 return 2;
191 }
192 options.nMaxPings = static_cast<size_t>(nMaxPings);
193
194 if (payloadSize < 0) {
195 std::cerr << "ERROR: payload size cannot be negative" << std::endl;
196 return 2;
197 }
198 options.payloadSize = static_cast<size_t>(payloadSize);
199
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -0700200 return Runner(options).run();
Eric Newberry94996d62015-05-07 13:48:46 -0700201}
202
203} // namespace server
204} // namespace ping
205} // namespace ndn
206
207int
Davide Pesaventoda85e252019-03-18 11:42:01 -0400208main(int argc, char* argv[])
Eric Newberry94996d62015-05-07 13:48:46 -0700209{
210 return ndn::ping::server::main(argc, argv);
Alexander Afanasyev1e7a7b22015-08-26 15:35:26 -0700211}