blob: dfe65382c1cec1a0dc1f6361f18f2a97b46bc675 [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 {
29
30class NdnTlvPingServer : boost::noncopyable
31{
32public:
33
34 explicit
35 NdnTlvPingServer(char* programName)
36 : 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)
69
70 m_freshnessPeriod = time::milliseconds(freshnessPeriod);
71 }
72
73 void
74 setMaximumPings(int maximumPings)
75 {
76 if (maximumPings <= 0)
77 usage();
78 m_maximumPings = maximumPings;
79 }
80
81 void
82 setPrefix(char* prefix)
83 {
84 m_prefix = prefix;
85 }
86
87 void
88 setPrintTimestamp()
89 {
90 m_isPrintTimestampSet = true;
91 }
92
93 bool
94 hasError() const
95 {
96 return m_hasError;
97 }
98
99 void
100 onInterest(const Name& name, const Interest& interest)
101 {
102 Name interestName = interest.getName();
103 if (m_isPrintTimestampSet)
104 std::cout << time::toIsoString(time::system_clock::now()) << " - ";
105 std::cout << "Interest Received - Ping Reference = "
106 << interestName.at(-1).toUri() << std::endl;
107 char responseContent[] = "NDN TLV Ping Response";
108 shared_ptr<Data> data = make_shared<Data>(interestName);
109 data->setFreshnessPeriod(m_freshnessPeriod);
110 data->setContent(reinterpret_cast<const uint8_t*>(responseContent),
111 sizeof(responseContent));
112 m_keyChain.sign(*data);
113 m_face.put(*data);
114 ++m_totalPings;
115 if (m_maximumPings > 0 && m_maximumPings == m_totalPings) {
116 std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
117 std::cout << "Shutting Down Ping Server (" << m_name << ").\n" << std::endl;
118 m_face.shutdown();
119 m_ioService.stop();
120 }
121 }
122
123 void
124 onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
125 {
126 std::cerr << "ERROR: Failed to register prefix in local hub's daemon" << std::endl;
127 std::cerr << "REASON: " << reason << std::endl;
128 m_hasError = true;
129 m_face.shutdown();
130 m_ioService.stop();
131 }
132
133 void
134 signalHandler()
135 {
136 std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
137 std::cout << "Shutting Down Ping Server (" << m_name.toUri() << ").\n" << std::endl;
138 m_face.shutdown();
139 exit(1);
140 }
141
142 void
143 run()
144 {
145 std::cout << "\n=== Ping Server " << m_prefix <<" ===\n" << std::endl;
146
147 boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
148 signalSet.async_wait(bind([this]() { signalHandler(); }));
149 m_name = m_prefix;
150 m_name.append("ping");
151 m_face.setInterestFilter(m_name,
152 bind(&NdnTlvPingServer::onInterest,
153 this, _1, _2),
154 bind(&NdnTlvPingServer::onRegisterFailed,
155 this, _1,_2));
156 try {
157 m_face.processEvents();
158 }
159 catch (std::exception& e) {
160 std::cerr << "ERROR: " << e.what() << std::endl;
161 m_hasError = true;
162 m_ioService.stop();
163 }
164 }
165
166private:
167 char* m_programName;
168 bool m_hasError;
169 bool m_isPrintTimestampSet;
170 time::milliseconds m_freshnessPeriod;
171 int m_maximumPings;
172 int m_totalPings;
173
174 char* m_prefix;
175 Name m_name;
176
177 boost::asio::io_service m_ioService;
178 KeyChain m_keyChain;
179 Face m_face;
180};
181
182}
183
184int
185main(int argc, char* argv[])
186{
187 int res;
188
189 ndn::NdnTlvPingServer ndnTlvPingServer(argv[0]);
190 while ((res = getopt(argc, argv, "hdtp:x:")) != -1)
191 {
192 switch (res) {
193 case 'h':
194 ndnTlvPingServer.usage();
195 break;
196 case 'p':
197 ndnTlvPingServer.setMaximumPings(atoi(optarg));
198 break;
199 case 'x':
200 ndnTlvPingServer.setFreshnessPeriod(atoi(optarg));
201 break;
202 case 't':
203 ndnTlvPingServer.setPrintTimestamp();
204 break;
205 default:
206 ndnTlvPingServer.usage();
207 break;
208 }
209 }
210
211 argc -= optind;
212 argv += optind;
213
214 if (argv[0] == 0)
215 ndnTlvPingServer.usage();
216
217 ndnTlvPingServer.setPrefix(argv[0]);
218 ndnTlvPingServer.run();
219
220 std::cout << std::endl;
221
222 if (ndnTlvPingServer.hasError())
223 return 1;
224 else
225 return 0;
226}