blob: 684891cfc3671e9f78bbdb4dba53be030df35404 [file] [log] [blame]
Junxiao Shi11b2ae92015-03-21 11:29:19 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2014 Arizona Board of Regents
4 *
5 * This file is part of ndn-tlv-ping (Ping Application for Named Data Networking).
6 *
7 * ndn-tlv-ping is a free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-tlv-ping is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * ndn-tlv-ping, e.g., in LICENSE file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
19 */
20
21#include <ndn-cxx/face.hpp>
22#include <ndn-cxx/name.hpp>
23#include <ndn-cxx/security/key-chain.hpp>
24
25#include <boost/asio.hpp>
26#include <boost/noncopyable.hpp>
27
28namespace ndn {
Junxiao Shi0c75f992015-03-24 21:39:47 -070029namespace ping {
Junxiao Shi11b2ae92015-03-21 11:29:19 -070030
Junxiao Shi0c75f992015-03-24 21:39:47 -070031class NdnPingServer : boost::noncopyable
Junxiao Shi11b2ae92015-03-21 11:29:19 -070032{
33public:
Junxiao Shi11b2ae92015-03-21 11:29:19 -070034 explicit
Junxiao Shi0c75f992015-03-24 21:39:47 -070035 NdnPingServer(char* programName)
Junxiao Shi11b2ae92015-03-21 11:29:19 -070036 : m_programName(programName)
37 , m_hasError(false)
38 , m_isPrintTimestampSet(false)
39 , m_freshnessPeriod(getMinimumFreshnessPeriod())
40 , m_maximumPings(-1)
41 , m_totalPings(0)
42 , m_face(m_ioService)
43 {
44 }
45
46 void
47 usage()
48 {
49 std::cout << "\n Usage:\n " << m_programName << " ndn:/name/prefix [options]\n"
50 " Starts a NDN ping server that responds to Interests with name"
51 " ndn:/name/prefix/ping/number.\n"
52 " [-x freshness] - set FreshnessSeconds\n"
53 " [-p] - specify number of pings to be satisfied (>=1)\n"
54 " [-t] - print timestamp\n"
55 " [-h] - print this message and exit\n\n";
56 exit(1);
57 }
58
59 time::milliseconds
60 getMinimumFreshnessPeriod()
61 {
62 return time::milliseconds(1000);
63 }
64
65 void
66 setFreshnessPeriod(int freshnessPeriod)
67 {
68 if (freshnessPeriod <= 0)
Junxiao Shi0c75f992015-03-24 21:39:47 -070069 usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -070070
71 m_freshnessPeriod = time::milliseconds(freshnessPeriod);
72 }
73
74 void
75 setMaximumPings(int maximumPings)
76 {
77 if (maximumPings <= 0)
78 usage();
Junxiao Shi0c75f992015-03-24 21:39:47 -070079
Junxiao Shi11b2ae92015-03-21 11:29:19 -070080 m_maximumPings = maximumPings;
81 }
82
83 void
84 setPrefix(char* prefix)
85 {
86 m_prefix = prefix;
87 }
88
89 void
90 setPrintTimestamp()
91 {
92 m_isPrintTimestampSet = true;
93 }
94
95 bool
96 hasError() const
97 {
98 return m_hasError;
99 }
100
101 void
102 onInterest(const Name& name, const Interest& interest)
103 {
104 Name interestName = interest.getName();
Junxiao Shi0c75f992015-03-24 21:39:47 -0700105
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700106 if (m_isPrintTimestampSet)
107 std::cout << time::toIsoString(time::system_clock::now()) << " - ";
108 std::cout << "Interest Received - Ping Reference = "
109 << interestName.at(-1).toUri() << std::endl;
Junxiao Shi0c75f992015-03-24 21:39:47 -0700110
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700111 char responseContent[] = "NDN TLV Ping Response";
112 shared_ptr<Data> data = make_shared<Data>(interestName);
113 data->setFreshnessPeriod(m_freshnessPeriod);
114 data->setContent(reinterpret_cast<const uint8_t*>(responseContent),
115 sizeof(responseContent));
116 m_keyChain.sign(*data);
117 m_face.put(*data);
Junxiao Shi0c75f992015-03-24 21:39:47 -0700118
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700119 ++m_totalPings;
120 if (m_maximumPings > 0 && m_maximumPings == m_totalPings) {
121 std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
122 std::cout << "Shutting Down Ping Server (" << m_name << ").\n" << std::endl;
123 m_face.shutdown();
124 m_ioService.stop();
125 }
126 }
127
128 void
129 onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
130 {
131 std::cerr << "ERROR: Failed to register prefix in local hub's daemon" << std::endl;
132 std::cerr << "REASON: " << reason << std::endl;
133 m_hasError = true;
134 m_face.shutdown();
135 m_ioService.stop();
136 }
137
138 void
139 signalHandler()
140 {
141 std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
142 std::cout << "Shutting Down Ping Server (" << m_name.toUri() << ").\n" << std::endl;
143 m_face.shutdown();
144 exit(1);
145 }
146
147 void
148 run()
149 {
150 std::cout << "\n=== Ping Server " << m_prefix <<" ===\n" << std::endl;
151
152 boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
153 signalSet.async_wait(bind([this]() { signalHandler(); }));
Junxiao Shi0c75f992015-03-24 21:39:47 -0700154
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700155 m_name = m_prefix;
156 m_name.append("ping");
157 m_face.setInterestFilter(m_name,
Junxiao Shi0c75f992015-03-24 21:39:47 -0700158 bind(&NdnPingServer::onInterest,
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700159 this, _1, _2),
Junxiao Shi0c75f992015-03-24 21:39:47 -0700160 bind(&NdnPingServer::onRegisterFailed,
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700161 this, _1,_2));
Junxiao Shi0c75f992015-03-24 21:39:47 -0700162
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700163 try {
164 m_face.processEvents();
165 }
166 catch (std::exception& e) {
167 std::cerr << "ERROR: " << e.what() << std::endl;
168 m_hasError = true;
169 m_ioService.stop();
170 }
171 }
172
173private:
174 char* m_programName;
175 bool m_hasError;
176 bool m_isPrintTimestampSet;
177 time::milliseconds m_freshnessPeriod;
178 int m_maximumPings;
179 int m_totalPings;
180
181 char* m_prefix;
182 Name m_name;
183
184 boost::asio::io_service m_ioService;
185 KeyChain m_keyChain;
186 Face m_face;
187};
188
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700189int
190main(int argc, char* argv[])
191{
192 int res;
193
Junxiao Shi0c75f992015-03-24 21:39:47 -0700194 NdnPingServer program(argv[0]);
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700195 while ((res = getopt(argc, argv, "hdtp:x:")) != -1)
196 {
197 switch (res) {
198 case 'h':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700199 program.usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700200 break;
201 case 'p':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700202 program.setMaximumPings(atoi(optarg));
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700203 break;
204 case 'x':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700205 program.setFreshnessPeriod(atoi(optarg));
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700206 break;
207 case 't':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700208 program.setPrintTimestamp();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700209 break;
210 default:
Junxiao Shi0c75f992015-03-24 21:39:47 -0700211 program.usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700212 break;
213 }
214 }
215
216 argc -= optind;
217 argv += optind;
218
219 if (argv[0] == 0)
Junxiao Shi0c75f992015-03-24 21:39:47 -0700220 program.usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700221
Junxiao Shi0c75f992015-03-24 21:39:47 -0700222 program.setPrefix(argv[0]);
223 program.run();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700224
225 std::cout << std::endl;
226
Junxiao Shi0c75f992015-03-24 21:39:47 -0700227 if (program.hasError())
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700228 return 1;
229 else
230 return 0;
231}
Junxiao Shi0c75f992015-03-24 21:39:47 -0700232
233} // namespace ping
234} // namespace ndn
235
236int
237main(int argc, char** argv)
238{
239 return ndn::ping::main(argc, argv);
240}