blob: d508e6ce8d7193921b79def80f12599bc8227f26 [file] [log] [blame]
Junxiao Shi1688ded2015-03-29 10:09:26 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Arizona Board of Regents.
4 *
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 */
Junxiao Shi11b2ae92015-03-21 11:29:19 -070019/**
20 * Copyright (C) 2014 Arizona Board of Regents
21 *
22 * This file is part of ndn-tlv-ping (Ping Application for Named Data Networking).
23 *
24 * ndn-tlv-ping is a free software: you can redistribute it and/or modify it under
25 * the terms of the GNU General Public License as published by the Free Software
26 * Foundation, either version 3 of the License, or (at your option) any later version.
27 *
28 * ndn-tlv-ping is distributed in the hope that it will be useful, but WITHOUT ANY
29 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
30 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License along with
33 * ndn-tlv-ping, e.g., in LICENSE file. If not, see <http://www.gnu.org/licenses/>.
34 *
35 * @author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
36 */
37
38#include <ndn-cxx/face.hpp>
39#include <ndn-cxx/name.hpp>
40#include <ndn-cxx/security/key-chain.hpp>
41
42#include <boost/asio.hpp>
43#include <boost/noncopyable.hpp>
44
45namespace ndn {
Junxiao Shi0c75f992015-03-24 21:39:47 -070046namespace ping {
Junxiao Shi11b2ae92015-03-21 11:29:19 -070047
Junxiao Shi0c75f992015-03-24 21:39:47 -070048class NdnPingServer : boost::noncopyable
Junxiao Shi11b2ae92015-03-21 11:29:19 -070049{
50public:
Junxiao Shi11b2ae92015-03-21 11:29:19 -070051 explicit
Junxiao Shi0c75f992015-03-24 21:39:47 -070052 NdnPingServer(char* programName)
Junxiao Shi11b2ae92015-03-21 11:29:19 -070053 : m_programName(programName)
54 , m_hasError(false)
55 , m_isPrintTimestampSet(false)
56 , m_freshnessPeriod(getMinimumFreshnessPeriod())
57 , m_maximumPings(-1)
58 , m_totalPings(0)
59 , m_face(m_ioService)
60 {
61 }
62
63 void
64 usage()
65 {
66 std::cout << "\n Usage:\n " << m_programName << " ndn:/name/prefix [options]\n"
67 " Starts a NDN ping server that responds to Interests with name"
68 " ndn:/name/prefix/ping/number.\n"
69 " [-x freshness] - set FreshnessSeconds\n"
70 " [-p] - specify number of pings to be satisfied (>=1)\n"
71 " [-t] - print timestamp\n"
72 " [-h] - print this message and exit\n\n";
73 exit(1);
74 }
75
76 time::milliseconds
77 getMinimumFreshnessPeriod()
78 {
79 return time::milliseconds(1000);
80 }
81
82 void
83 setFreshnessPeriod(int freshnessPeriod)
84 {
85 if (freshnessPeriod <= 0)
Junxiao Shi0c75f992015-03-24 21:39:47 -070086 usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -070087
88 m_freshnessPeriod = time::milliseconds(freshnessPeriod);
89 }
90
91 void
92 setMaximumPings(int maximumPings)
93 {
94 if (maximumPings <= 0)
95 usage();
Junxiao Shi0c75f992015-03-24 21:39:47 -070096
Junxiao Shi11b2ae92015-03-21 11:29:19 -070097 m_maximumPings = maximumPings;
98 }
99
100 void
101 setPrefix(char* prefix)
102 {
103 m_prefix = prefix;
104 }
105
106 void
107 setPrintTimestamp()
108 {
109 m_isPrintTimestampSet = true;
110 }
111
112 bool
113 hasError() const
114 {
115 return m_hasError;
116 }
117
118 void
119 onInterest(const Name& name, const Interest& interest)
120 {
121 Name interestName = interest.getName();
Junxiao Shi0c75f992015-03-24 21:39:47 -0700122
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700123 if (m_isPrintTimestampSet)
124 std::cout << time::toIsoString(time::system_clock::now()) << " - ";
125 std::cout << "Interest Received - Ping Reference = "
126 << interestName.at(-1).toUri() << std::endl;
Junxiao Shi0c75f992015-03-24 21:39:47 -0700127
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700128 char responseContent[] = "NDN TLV Ping Response";
129 shared_ptr<Data> data = make_shared<Data>(interestName);
130 data->setFreshnessPeriod(m_freshnessPeriod);
131 data->setContent(reinterpret_cast<const uint8_t*>(responseContent),
132 sizeof(responseContent));
133 m_keyChain.sign(*data);
134 m_face.put(*data);
Junxiao Shi0c75f992015-03-24 21:39:47 -0700135
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700136 ++m_totalPings;
137 if (m_maximumPings > 0 && m_maximumPings == m_totalPings) {
138 std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
139 std::cout << "Shutting Down Ping Server (" << m_name << ").\n" << std::endl;
140 m_face.shutdown();
141 m_ioService.stop();
142 }
143 }
144
145 void
146 onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
147 {
148 std::cerr << "ERROR: Failed to register prefix in local hub's daemon" << std::endl;
149 std::cerr << "REASON: " << reason << std::endl;
150 m_hasError = true;
151 m_face.shutdown();
152 m_ioService.stop();
153 }
154
155 void
156 signalHandler()
157 {
158 std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
159 std::cout << "Shutting Down Ping Server (" << m_name.toUri() << ").\n" << std::endl;
160 m_face.shutdown();
161 exit(1);
162 }
163
164 void
165 run()
166 {
167 std::cout << "\n=== Ping Server " << m_prefix <<" ===\n" << std::endl;
168
169 boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
170 signalSet.async_wait(bind([this]() { signalHandler(); }));
Junxiao Shi0c75f992015-03-24 21:39:47 -0700171
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700172 m_name = m_prefix;
173 m_name.append("ping");
174 m_face.setInterestFilter(m_name,
Junxiao Shi0c75f992015-03-24 21:39:47 -0700175 bind(&NdnPingServer::onInterest,
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700176 this, _1, _2),
Junxiao Shi0c75f992015-03-24 21:39:47 -0700177 bind(&NdnPingServer::onRegisterFailed,
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700178 this, _1,_2));
Junxiao Shi0c75f992015-03-24 21:39:47 -0700179
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700180 try {
181 m_face.processEvents();
182 }
183 catch (std::exception& e) {
184 std::cerr << "ERROR: " << e.what() << std::endl;
185 m_hasError = true;
186 m_ioService.stop();
187 }
188 }
189
190private:
191 char* m_programName;
192 bool m_hasError;
193 bool m_isPrintTimestampSet;
194 time::milliseconds m_freshnessPeriod;
195 int m_maximumPings;
196 int m_totalPings;
197
198 char* m_prefix;
199 Name m_name;
200
201 boost::asio::io_service m_ioService;
202 KeyChain m_keyChain;
203 Face m_face;
204};
205
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700206int
207main(int argc, char* argv[])
208{
209 int res;
210
Junxiao Shi0c75f992015-03-24 21:39:47 -0700211 NdnPingServer program(argv[0]);
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700212 while ((res = getopt(argc, argv, "hdtp:x:")) != -1)
213 {
214 switch (res) {
215 case 'h':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700216 program.usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700217 break;
218 case 'p':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700219 program.setMaximumPings(atoi(optarg));
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700220 break;
221 case 'x':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700222 program.setFreshnessPeriod(atoi(optarg));
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700223 break;
224 case 't':
Junxiao Shi0c75f992015-03-24 21:39:47 -0700225 program.setPrintTimestamp();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700226 break;
227 default:
Junxiao Shi0c75f992015-03-24 21:39:47 -0700228 program.usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700229 break;
230 }
231 }
232
233 argc -= optind;
234 argv += optind;
235
236 if (argv[0] == 0)
Junxiao Shi0c75f992015-03-24 21:39:47 -0700237 program.usage();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700238
Junxiao Shi0c75f992015-03-24 21:39:47 -0700239 program.setPrefix(argv[0]);
240 program.run();
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700241
242 std::cout << std::endl;
243
Junxiao Shi0c75f992015-03-24 21:39:47 -0700244 if (program.hasError())
Junxiao Shi11b2ae92015-03-21 11:29:19 -0700245 return 1;
246 else
247 return 0;
248}
Junxiao Shi0c75f992015-03-24 21:39:47 -0700249
250} // namespace ping
251} // namespace ndn
252
253int
254main(int argc, char** argv)
255{
256 return ndn::ping::main(argc, argv);
257}