blob: a6d8fef3be099e774b61f937190ce39d2ddca676 [file] [log] [blame]
Davide Pesavento35185332019-01-14 04:00:15 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Eric Newberryc8e18582018-05-31 19:27:01 -07002/*
Davide Pesavento35185332019-01-14 04:00:15 -05003 * Copyright (c) 2014-2019, Arizona Board of Regents.
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -08004 *
Davide Pesaventod0b59982015-02-27 19:15:15 +01005 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080017 *
18 * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
19 */
20
Eric Newberryc8e18582018-05-31 19:27:01 -070021#include "logger.hpp"
Davide Pesavento35185332019-01-14 04:00:15 -050022#include "util.hpp"
Eric Newberryc8e18582018-05-31 19:27:01 -070023
Davide Pesavento35185332019-01-14 04:00:15 -050024#include <ndn-cxx/data.hpp>
Eric Newberryc8e18582018-05-31 19:27:01 -070025#include <ndn-cxx/face.hpp>
26#include <ndn-cxx/security/key-chain.hpp>
27#include <ndn-cxx/security/signing-info.hpp>
28#include <ndn-cxx/util/backports.hpp>
Davide Pesavento35185332019-01-14 04:00:15 -050029#include <ndn-cxx/util/random.hpp>
30
31#include <cctype>
32#include <limits>
33#include <sstream>
34#include <vector>
jeraldabraham420dbf02014-04-25 22:58:31 -070035
Davide Pesaventod0b59982015-02-27 19:15:15 +010036#include <boost/asio/io_service.hpp>
37#include <boost/asio/signal_set.hpp>
jeraldabraham420dbf02014-04-25 22:58:31 -070038#include <boost/noncopyable.hpp>
Davide Pesavento35185332019-01-14 04:00:15 -050039#include <boost/program_options/options_description.hpp>
40#include <boost/program_options/parsers.hpp>
41#include <boost/program_options/variables_map.hpp>
42#include <boost/thread/thread.hpp>
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080043
Davide Pesavento35185332019-01-14 04:00:15 -050044namespace po = boost::program_options;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080045
46namespace ndn {
47
jeraldabraham420dbf02014-04-25 22:58:31 -070048class NdnTrafficServer : boost::noncopyable
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080049{
50public:
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070051 explicit
Davide Pesavento35185332019-01-14 04:00:15 -050052 NdnTrafficServer(const std::string& configFile)
53 : m_signalSet(m_ioService, SIGINT, SIGTERM)
54 , m_logger("NdnTrafficServer")
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070055 , m_face(m_ioService)
Davide Pesavento35185332019-01-14 04:00:15 -050056 , m_configurationFile(configFile)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080057 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080058 }
59
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070060 bool
61 hasError() const
62 {
63 return m_hasError;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080064 }
65
66 void
Davide Pesavento35185332019-01-14 04:00:15 -050067 setMaximumInterests(uint64_t maxInterests)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080068 {
Davide Pesavento35185332019-01-14 04:00:15 -050069 m_nMaximumInterests = maxInterests;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080070 }
71
72 void
Davide Pesavento35185332019-01-14 04:00:15 -050073 setContentDelay(time::milliseconds delay)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080074 {
Davide Pesavento35185332019-01-14 04:00:15 -050075 BOOST_ASSERT(delay >= 0_ms);
76 m_contentDelay = delay;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080077 }
78
79 void
jeraldabraham420dbf02014-04-25 22:58:31 -070080 setQuietLogging()
81 {
Davide Pesavento35185332019-01-14 04:00:15 -050082 m_wantQuiet = true;
jeraldabraham420dbf02014-04-25 22:58:31 -070083 }
84
85 void
Davide Pesavento35185332019-01-14 04:00:15 -050086 run()
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080087 {
Davide Pesavento35185332019-01-14 04:00:15 -050088 m_logger.initializeLog(to_string(random::generateWord32()));
89 initializeTrafficConfiguration();
Davide Pesaventod0b59982015-02-27 19:15:15 +010090
Davide Pesavento35185332019-01-14 04:00:15 -050091 if (m_nMaximumInterests == 0) {
92 logStatistics();
93 return;
94 }
Davide Pesaventod0b59982015-02-27 19:15:15 +010095
Davide Pesavento35185332019-01-14 04:00:15 -050096 m_signalSet.async_wait([this] (const boost::system::error_code&, int) {
97 if (m_nMaximumInterests && m_nInterestsReceived < *m_nMaximumInterests) {
98 m_hasError = true;
99 }
100 stop();
101 });
102
103 for (std::size_t id = 0; id < m_trafficPatterns.size(); id++) {
104 m_registeredPrefixes.push_back(
105 m_face.setInterestFilter(m_trafficPatterns[id].m_name,
106 [=] (auto&&, const auto& interest) { this->onInterest(interest, id); },
107 nullptr,
108 [=] (auto&&, const auto& reason) { this->onRegisterFailed(reason, id); }));
109 }
110
111 try {
112 m_face.processEvents();
113 }
114 catch (const std::exception& e) {
115 m_logger.log("ERROR: "s + e.what(), true, true);
116 m_hasError = true;
117 m_ioService.stop();
118 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800119 }
120
Davide Pesavento35185332019-01-14 04:00:15 -0500121private:
122 class DataTrafficConfiguration
123 {
124 public:
125 void
126 printTrafficConfiguration(Logger& logger) const
127 {
128 std::ostringstream os;
129
130 if (!m_name.empty()) {
131 os << "Name=" << m_name << ", ";
132 }
133 if (m_contentDelay >= 0_ms) {
134 os << "ContentDelay=" << m_contentDelay.count() << ", ";
135 }
136 if (m_freshnessPeriod >= 0_ms) {
137 os << "FreshnessPeriod=" << m_freshnessPeriod.count() << ", ";
138 }
139 if (m_contentType) {
140 os << "ContentType=" << *m_contentType << ", ";
141 }
142 if (m_contentLength) {
143 os << "ContentBytes=" << *m_contentLength << ", ";
144 }
145 if (!m_content.empty()) {
146 os << "Content=" << m_content << ", ";
147 }
148 os << "SigningInfo=" << m_signingInfo;
149
150 logger.log(os.str(), false, false);
151 }
152
153 bool
154 processConfigurationDetail(const std::string& detail, Logger& logger, int lineNumber)
155 {
156 std::string parameter, value;
157 if (parseParameterAndValue(detail, parameter, value)) {
158 if (parameter == "Name") {
159 m_name = value;
160 }
161 else if (parameter == "ContentDelay") {
162 m_contentDelay = time::milliseconds(std::stoul(value));
163 }
164 else if (parameter == "FreshnessPeriod") {
165 m_freshnessPeriod = time::milliseconds(std::stoul(value));
166 }
167 else if (parameter == "ContentType") {
168 m_contentType = std::stoul(value);
169 }
170 else if (parameter == "ContentBytes") {
171 m_contentLength = std::stoul(value);
172 }
173 else if (parameter == "Content") {
174 m_content = value;
175 }
176 else if (parameter == "SigningInfo") {
177 m_signingInfo = security::SigningInfo(value);
178 }
179 else {
180 logger.log("Line " + to_string(lineNumber) +
181 " - Unknown parameter '" + parameter + "'", false, true);
182 }
183 }
184 else {
185 logger.log("Line " + to_string(lineNumber) +
186 " - Invalid traffic configuration line: " + detail, false, true);
187 return false;
188 }
189 return true;
190 }
191
192 bool
193 checkTrafficDetailCorrectness() const
194 {
195 return true;
196 }
197
198 public:
199 std::string m_name;
200 time::milliseconds m_contentDelay = -1_ms;
201 time::milliseconds m_freshnessPeriod = -1_ms;
202 optional<uint32_t> m_contentType;
203 optional<std::size_t> m_contentLength;
204 std::string m_content;
205 security::SigningInfo m_signingInfo;
206 uint64_t m_nInterestsReceived = 0;
207 };
208
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800209 void
210 logStatistics()
211 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800212 m_logger.log("\n\n== Interest Traffic Report ==\n", false, true);
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700213 m_logger.log("Total Traffic Pattern Types = " +
Spencer Lee8e990232015-11-27 03:54:39 -0700214 to_string(m_trafficPatterns.size()), false, true);
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700215 m_logger.log("Total Interests Received = " +
Spencer Lee8e990232015-11-27 03:54:39 -0700216 to_string(m_nInterestsReceived), false, true);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100217
Eric Newberryc8e18582018-05-31 19:27:01 -0700218 for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++) {
219 m_logger.log("\nTraffic Pattern Type #" + to_string(patternId + 1), false, true);
220 m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
Davide Pesavento35185332019-01-14 04:00:15 -0500221 m_logger.log("Total Interests Received = " +
222 to_string(m_trafficPatterns[patternId].m_nInterestsReceived) + "\n", false, true);
Eric Newberryc8e18582018-05-31 19:27:01 -0700223 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800224 }
225
226 bool
Davide Pesavento35185332019-01-14 04:00:15 -0500227 checkTrafficPatternCorrectness() const
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800228 {
229 return true;
230 }
231
232 void
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700233 parseConfigurationFile()
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800234 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800235 std::ifstream patternFile;
Davide Pesavento35185332019-01-14 04:00:15 -0500236 m_logger.log("Parsing traffic configuration file: " + m_configurationFile, true, true);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100237
Davide Pesavento35185332019-01-14 04:00:15 -0500238 patternFile.open(m_configurationFile.data());
Eric Newberryc8e18582018-05-31 19:27:01 -0700239 if (patternFile.is_open()) {
240 int lineNumber = 0;
Davide Pesavento35185332019-01-14 04:00:15 -0500241 std::string patternLine;
Eric Newberryc8e18582018-05-31 19:27:01 -0700242 while (getline(patternFile, patternLine)) {
243 lineNumber++;
244 if (std::isalpha(patternLine[0])) {
245 DataTrafficConfiguration dataData;
246 bool shouldSkipLine = false;
247 if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
248 while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
249 lineNumber++;
250 if (!dataData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
251 shouldSkipLine = true;
252 break;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800253 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700254 }
255 lineNumber++;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800256 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700257 else {
258 shouldSkipLine = true;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800259 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700260 if (!shouldSkipLine) {
261 if (dataData.checkTrafficDetailCorrectness()) {
262 m_trafficPatterns.push_back(dataData);
263 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800264 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700265 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800266 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700267 patternFile.close();
268
269 if (!checkTrafficPatternCorrectness()) {
Davide Pesavento35185332019-01-14 04:00:15 -0500270 m_logger.log("ERROR: Traffic configuration provided is not proper - " +
Eric Newberryc8e18582018-05-31 19:27:01 -0700271 m_configurationFile, false, true);
Davide Pesavento35185332019-01-14 04:00:15 -0500272 exit(2);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800273 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700274
Davide Pesavento35185332019-01-14 04:00:15 -0500275 m_logger.log("Traffic configuration file processing completed.\n", true, false);
Eric Newberryc8e18582018-05-31 19:27:01 -0700276 for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++) {
Davide Pesavento35185332019-01-14 04:00:15 -0500277 m_logger.log("Traffic Pattern Type #" + to_string(patternId + 1), false, false);
Eric Newberryc8e18582018-05-31 19:27:01 -0700278 m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
279 m_logger.log("", false, false);
280 }
281 }
282 else {
Davide Pesavento35185332019-01-14 04:00:15 -0500283 m_logger.log("ERROR: Unable to open traffic configuration file: " + m_configurationFile, false, true);
284 exit(2);
Eric Newberryc8e18582018-05-31 19:27:01 -0700285 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800286 }
287
288 void
289 initializeTrafficConfiguration()
290 {
Davide Pesavento35185332019-01-14 04:00:15 -0500291 namespace fs = boost::filesystem;
292
293 fs::path configPath(m_configurationFile);
294 if (fs::exists(configPath)) {
295 if (fs::is_regular_file(configPath)) {
Eric Newberryc8e18582018-05-31 19:27:01 -0700296 parseConfigurationFile();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800297 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700298 else {
Davide Pesavento35185332019-01-14 04:00:15 -0500299 m_logger.log("ERROR: Traffic configuration file is not a regular file: " +
Eric Newberryc8e18582018-05-31 19:27:01 -0700300 m_configurationFile, false, true);
Davide Pesavento35185332019-01-14 04:00:15 -0500301 exit(2);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800302 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700303 }
304 else {
Davide Pesavento35185332019-01-14 04:00:15 -0500305 m_logger.log("ERROR: Traffic configuration file does not exist: " +
Eric Newberryc8e18582018-05-31 19:27:01 -0700306 m_configurationFile, false, true);
Davide Pesavento35185332019-01-14 04:00:15 -0500307 exit(2);
Eric Newberryc8e18582018-05-31 19:27:01 -0700308 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800309 }
310
311 static std::string
Davide Pesavento35185332019-01-14 04:00:15 -0500312 getRandomByteString(std::size_t length)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800313 {
Davide Pesavento35185332019-01-14 04:00:15 -0500314 // per ISO C++ std, cannot instantiate uniform_int_distribution with char
315 static std::uniform_int_distribution<short> dist(std::numeric_limits<char>::min(),
316 std::numeric_limits<char>::max());
317
318 std::string s;
319 s.reserve(length);
320 for (std::size_t i = 0; i < length; i++) {
321 s += static_cast<char>(dist(random::getRandomNumberEngine()));
Eric Newberryc8e18582018-05-31 19:27:01 -0700322 }
Davide Pesavento35185332019-01-14 04:00:15 -0500323 return s;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800324 }
325
326 void
Davide Pesavento35185332019-01-14 04:00:15 -0500327 onInterest(const Interest& interest, std::size_t patternId)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800328 {
Spencer Leee7a5b742015-10-29 02:18:11 -0700329 auto& pattern = m_trafficPatterns[patternId];
330
Davide Pesavento35185332019-01-14 04:00:15 -0500331 if (!m_nMaximumInterests || m_nInterestsReceived < *m_nMaximumInterests) {
Eric Newberryc8e18582018-05-31 19:27:01 -0700332 Data data(interest.getName());
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800333
Davide Pesavento35185332019-01-14 04:00:15 -0500334 if (pattern.m_freshnessPeriod >= 0_ms)
Eric Newberryc8e18582018-05-31 19:27:01 -0700335 data.setFreshnessPeriod(pattern.m_freshnessPeriod);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700336
Davide Pesavento35185332019-01-14 04:00:15 -0500337 if (pattern.m_contentType)
338 data.setContentType(*pattern.m_contentType);
339
Eric Newberryc8e18582018-05-31 19:27:01 -0700340 std::string content;
Davide Pesavento35185332019-01-14 04:00:15 -0500341 if (pattern.m_contentLength > 0)
342 content = getRandomByteString(*pattern.m_contentLength);
Eric Newberryc8e18582018-05-31 19:27:01 -0700343 if (!pattern.m_content.empty())
344 content = pattern.m_content;
Davide Pesavento35185332019-01-14 04:00:15 -0500345 data.setContent(reinterpret_cast<const uint8_t*>(content.data()), content.length());
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700346
Eric Newberryc8e18582018-05-31 19:27:01 -0700347 m_keyChain.sign(data, pattern.m_signingInfo);
Spencer Leee7a5b742015-10-29 02:18:11 -0700348
Eric Newberryc8e18582018-05-31 19:27:01 -0700349 m_nInterestsReceived++;
350 pattern.m_nInterestsReceived++;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100351
Davide Pesavento35185332019-01-14 04:00:15 -0500352 if (!m_wantQuiet) {
353 auto logLine = "Interest received - PatternType=" + to_string(patternId + 1) +
354 ", GlobalID=" + to_string(m_nInterestsReceived) +
355 ", LocalID=" + to_string(pattern.m_nInterestsReceived) +
356 ", Name=" + pattern.m_name;
Eric Newberryc8e18582018-05-31 19:27:01 -0700357 m_logger.log(logLine, true, false);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700358 }
Eric Newberryc8e18582018-05-31 19:27:01 -0700359
Davide Pesavento35185332019-01-14 04:00:15 -0500360 if (pattern.m_contentDelay > 0_ms)
361 boost::this_thread::sleep_for(pattern.m_contentDelay);
362 if (m_contentDelay > 0_ms)
363 boost::this_thread::sleep_for(m_contentDelay);
364
Eric Newberryc8e18582018-05-31 19:27:01 -0700365 m_face.put(data);
366 }
Davide Pesavento35185332019-01-14 04:00:15 -0500367
368 if (m_nMaximumInterests && m_nInterestsReceived >= *m_nMaximumInterests) {
Eric Newberryc8e18582018-05-31 19:27:01 -0700369 logStatistics();
Davide Pesavento35185332019-01-14 04:00:15 -0500370 m_registeredPrefixes.clear();
Eric Newberry51459402018-06-28 00:06:18 -0700371 m_signalSet.cancel();
Eric Newberryc8e18582018-05-31 19:27:01 -0700372 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800373 }
374
375 void
Davide Pesavento35185332019-01-14 04:00:15 -0500376 onRegisterFailed(const std::string& reason, std::size_t patternId)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800377 {
Davide Pesavento35185332019-01-14 04:00:15 -0500378 auto logLine = "Prefix registration failed - PatternType=" + to_string(patternId + 1) +
379 ", Name=" + m_trafficPatterns[patternId].m_name +
380 ", Reason=" + reason;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800381 m_logger.log(logLine, true, true);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100382
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700383 m_nRegistrationsFailed++;
Eric Newberryc8e18582018-05-31 19:27:01 -0700384 if (m_nRegistrationsFailed == m_trafficPatterns.size()) {
385 m_hasError = true;
Davide Pesavento35185332019-01-14 04:00:15 -0500386 stop();
Eric Newberryc8e18582018-05-31 19:27:01 -0700387 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800388 }
389
390 void
Davide Pesavento35185332019-01-14 04:00:15 -0500391 stop()
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800392 {
Davide Pesavento35185332019-01-14 04:00:15 -0500393 logStatistics();
394 m_face.shutdown();
395 m_ioService.stop();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800396 }
397
398private:
Alexander Afanasyev976c3972014-05-26 17:03:40 +0300399 boost::asio::io_service m_ioService;
Eric Newberry51459402018-06-28 00:06:18 -0700400 boost::asio::signal_set m_signalSet;
Davide Pesavento35185332019-01-14 04:00:15 -0500401 Logger m_logger;
402 Face m_face;
403 KeyChain m_keyChain;
404
405 std::string m_configurationFile;
406 optional<uint64_t> m_nMaximumInterests;
407 time::milliseconds m_contentDelay = 0_ms;
408 bool m_wantQuiet = false;
409
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700410 std::vector<DataTrafficConfiguration> m_trafficPatterns;
Davide Pesavento35185332019-01-14 04:00:15 -0500411 std::vector<ScopedRegisteredPrefixHandle> m_registeredPrefixes;
412 uint64_t m_nRegistrationsFailed = 0;
413 uint64_t m_nInterestsReceived = 0;
414 bool m_hasError = false;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800415};
416
417} // namespace ndn
418
Davide Pesavento35185332019-01-14 04:00:15 -0500419static void
420usage(std::ostream& os, const std::string& programName, const po::options_description& desc)
421{
422 os << "Usage: " << programName << " [options] <Traffic_Configuration_File>\n"
423 << "\n"
424 << "Respond to Interests as per provided Traffic_Configuration_File.\n"
425 << "Multiple prefixes can be configured for handling.\n"
426 << "Set the environment variable NDN_TRAFFIC_LOGFOLDER to redirect output to a log file.\n"
427 << "\n"
428 << desc;
429}
430
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700431int
432main(int argc, char* argv[])
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800433{
Davide Pesavento35185332019-01-14 04:00:15 -0500434 std::string configFile;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100435
Davide Pesavento35185332019-01-14 04:00:15 -0500436 po::options_description visibleOptions("Options");
437 visibleOptions.add_options()
438 ("help,h", "print this help message and exit")
439 ("count,c", po::value<int>(), "maximum number of Interests to respond to")
440 ("delay,d", po::value<ndn::time::milliseconds::rep>()->default_value(0),
441 "wait this amount of milliseconds before responding to each Interest")
442 ("quiet,q", po::bool_switch(), "turn off logging of Interest reception/Data generation")
443 ;
444
445 po::options_description hiddenOptions;
446 hiddenOptions.add_options()
447 ("config-file", po::value<std::string>(&configFile))
448 ;
449
450 po::positional_options_description posOptions;
451 posOptions.add("config-file", -1);
452
453 po::options_description allOptions;
454 allOptions.add(visibleOptions).add(hiddenOptions);
455
456 po::variables_map vm;
457 try {
458 po::store(po::command_line_parser(argc, argv).options(allOptions).positional(posOptions).run(), vm);
459 po::notify(vm);
460 }
461 catch (const po::error& e) {
462 std::cerr << "ERROR: " << e.what() << std::endl;
463 return 2;
464 }
465 catch (const boost::bad_any_cast& e) {
466 std::cerr << "ERROR: " << e.what() << std::endl;
467 return 2;
468 }
469
470 if (vm.count("help") > 0) {
471 usage(std::cout, argv[0], visibleOptions);
472 return 0;
473 }
474
475 if (configFile.empty()) {
476 usage(std::cerr, argv[0], visibleOptions);
477 return 2;
478 }
479
480 ndn::NdnTrafficServer server(configFile);
481
482 if (vm.count("count") > 0) {
483 int count = vm["count"].as<int>();
484 if (count < 0) {
485 std::cerr << "ERROR: the argument for option '--count' cannot be negative" << std::endl;
486 return 2;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800487 }
Davide Pesavento35185332019-01-14 04:00:15 -0500488 server.setMaximumInterests(static_cast<uint64_t>(count));
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800489 }
490
Davide Pesavento35185332019-01-14 04:00:15 -0500491 if (vm.count("delay") > 0) {
492 ndn::time::milliseconds delay(vm["delay"].as<ndn::time::milliseconds::rep>());
493 if (delay < ndn::time::milliseconds::zero()) {
494 std::cerr << "ERROR: the argument for option '--delay' cannot be negative" << std::endl;
495 return 2;
496 }
497 server.setContentDelay(delay);
Eric Newberryc8e18582018-05-31 19:27:01 -0700498 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800499
Davide Pesavento35185332019-01-14 04:00:15 -0500500 if (vm["quiet"].as<bool>()) {
501 server.setQuietLogging();
502 }
503
Davide Pesaventod0b59982015-02-27 19:15:15 +0100504 server.run();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800505
Davide Pesavento35185332019-01-14 04:00:15 -0500506 return server.hasError() ? 1 : 0;
Eric Newberryc8e18582018-05-31 19:27:01 -0700507}