blob: e9ba3391208595addd5e05b0af95cbd0574f9538 [file] [log] [blame]
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Davide Pesaventod0b59982015-02-27 19:15:15 +01003 * Copyright (C) 2014-2015 University of Arizona.
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
Davide Pesaventod0b59982015-02-27 19:15:15 +010021#include <cctype>
22#include <cstdlib>
23#include <fstream>
24#include <string>
25#include <unistd.h>
26#include <vector>
jeraldabraham420dbf02014-04-25 22:58:31 -070027
Davide Pesaventod0b59982015-02-27 19:15:15 +010028#include <boost/asio/io_service.hpp>
29#include <boost/asio/signal_set.hpp>
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080030#include <boost/filesystem.hpp>
jeraldabraham420dbf02014-04-25 22:58:31 -070031#include <boost/noncopyable.hpp>
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080032
jeraldabraham420dbf02014-04-25 22:58:31 -070033#include <ndn-cxx/face.hpp>
34#include <ndn-cxx/security/key-chain.hpp>
Spencer Leee7a5b742015-10-29 02:18:11 -070035#include <ndn-cxx/security/signing-helpers.hpp>
Spencer Lee8e990232015-11-27 03:54:39 -070036#include <ndn-cxx/util/backports.hpp>
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080037
38#include "logger.hpp"
39
40namespace ndn {
41
jeraldabraham420dbf02014-04-25 22:58:31 -070042class NdnTrafficServer : boost::noncopyable
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080043{
44public:
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070045 explicit
Davide Pesaventod0b59982015-02-27 19:15:15 +010046 NdnTrafficServer(const char* programName)
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070047 : m_logger("NdnTrafficServer")
48 , m_programName(programName)
49 , m_hasError(false)
jeraldabraham420dbf02014-04-25 22:58:31 -070050 , m_hasQuietLogging(false)
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070051 , m_nRegistrationsFailed(0)
52 , m_nMaximumInterests(-1)
53 , m_nInterestsReceived(0)
54 , m_contentDelay(time::milliseconds(-1))
Spencer Lee8e990232015-11-27 03:54:39 -070055 , m_instanceId(to_string(std::rand()))
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070056 , m_face(m_ioService)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080057 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080058 }
59
60 class DataTrafficConfiguration
61 {
62 public:
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080063 DataTrafficConfiguration()
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070064 : m_contentType(-1)
65 , m_freshnessPeriod(time::milliseconds(-1))
66 , m_contentBytes(-1)
67 , m_contentDelay(time::milliseconds(-1))
68 , m_nInterestsReceived(0)
Spencer Leee7a5b742015-10-29 02:18:11 -070069 , m_signWithSha256(false)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080070 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080071 }
72
73 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -070074 printTrafficConfiguration(Logger& logger)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080075 {
Davide Pesaventod0b59982015-02-27 19:15:15 +010076 std::string detail;
77
78 if (!m_name.empty())
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070079 detail += "Name=" + m_name + ", ";
80 if (m_contentType >= 0)
Spencer Lee8e990232015-11-27 03:54:39 -070081 detail += "ContentType=" + to_string(m_contentType) + ", ";
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070082 if (m_freshnessPeriod >= time::milliseconds(0))
83 detail += "FreshnessPeriod=" +
Spencer Lee8e990232015-11-27 03:54:39 -070084 to_string(static_cast<int>(m_freshnessPeriod.count())) + ", ";
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070085 if (m_contentBytes >= 0)
Spencer Lee8e990232015-11-27 03:54:39 -070086 detail += "ContentBytes=" + to_string(m_contentBytes) + ", ";
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070087 if (m_contentDelay >= time::milliseconds(0))
Spencer Lee8e990232015-11-27 03:54:39 -070088 detail += "ContentDelay=" + to_string(m_contentDelay.count()) + ", ";
Davide Pesaventod0b59982015-02-27 19:15:15 +010089 if (!m_content.empty())
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070090 detail += "Content=" + m_content + ", ";
Spencer Lee8e990232015-11-27 03:54:39 -070091 detail += "SignWithSha256=" + to_string(m_signWithSha256) + ", ";
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080092 if (detail.length() >= 2)
jeraldabrahamcc3c6c92014-03-28 02:21:45 -070093 detail = detail.substr(0, detail.length() - 2);
Davide Pesaventod0b59982015-02-27 19:15:15 +010094
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080095 logger.log(detail, false, false);
96 }
97
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080098 bool
Davide Pesaventod0b59982015-02-27 19:15:15 +010099 extractParameterValue(const std::string& detail, std::string& parameter, std::string& value)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800100 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800101 std::string allowedCharacters = ":/+._-%";
Davide Pesaventod0b59982015-02-27 19:15:15 +0100102 std::size_t i = 0;
103
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800104 parameter = "";
105 value = "";
Davide Pesaventod0b59982015-02-27 19:15:15 +0100106 while (detail[i] != '=' && i < detail.length()) {
107 parameter += detail[i];
108 i++;
109 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800110 if (i == detail.length())
111 return false;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100112
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800113 i++;
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700114 while ((std::isalnum(detail[i]) ||
115 allowedCharacters.find(detail[i]) != std::string::npos) &&
Davide Pesaventod0b59982015-02-27 19:15:15 +0100116 i < detail.length()) {
117 value += detail[i];
118 i++;
119 }
120
121 if (parameter.empty() || value.empty())
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800122 return false;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100123 else
124 return true;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800125 }
126
127 bool
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700128 processConfigurationDetail(const std::string& detail,
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700129 Logger& logger,
130 int lineNumber)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800131 {
132 std::string parameter, value;
Spencer Leee7a5b742015-10-29 02:18:11 -0700133 if (extractParameterValue(detail, parameter, value)) {
134 if (parameter == "Name") {
135 m_name = value;
136 }
137 else if (parameter == "ContentType") {
138 m_contentType = std::stoi(value);
139 }
140 else if (parameter == "FreshnessPeriod") {
141 m_freshnessPeriod = time::milliseconds(std::stoi(value));
142 }
143 else if (parameter == "ContentDelay") {
144 m_contentDelay = time::milliseconds(std::stoi(value));
145 }
146 else if (parameter == "ContentBytes") {
147 m_contentBytes = std::stoi(value);
148 }
149 else if (parameter == "Content") {
150 m_content = value;
151 }
152 else if (parameter == "SignWithSha256") {
153 if (value == "0") {
154 m_signWithSha256 = false;
155 }
156 else if (value == "1") {
157 m_signWithSha256 = true;
158 }
159 else {
Spencer Lee8e990232015-11-27 03:54:39 -0700160 logger.log("Line " + to_string(lineNumber) +
Spencer Leee7a5b742015-10-29 02:18:11 -0700161 " \t- Invalid SignWithSha256 Value='" + value + "'", false, true);
162 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800163 }
Spencer Leee7a5b742015-10-29 02:18:11 -0700164 else {
Spencer Lee8e990232015-11-27 03:54:39 -0700165 logger.log("Line " + to_string(lineNumber) +
Spencer Leee7a5b742015-10-29 02:18:11 -0700166 " \t- Invalid Parameter='" + parameter + "'", false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800167 }
Spencer Leee7a5b742015-10-29 02:18:11 -0700168 }
169 else {
Spencer Lee8e990232015-11-27 03:54:39 -0700170 logger.log("Line " + to_string(lineNumber) +
Spencer Leee7a5b742015-10-29 02:18:11 -0700171 " \t- Improper Traffic Configuration Line - " + detail, false, true);
172 return false;
173 }
174
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800175 return true;
176 }
177
178 bool
179 checkTrafficDetailCorrectness()
180 {
181 return true;
182 }
183
Davide Pesaventod0b59982015-02-27 19:15:15 +0100184 private:
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700185 std::string m_name;
186 int m_contentType;
187 time::milliseconds m_freshnessPeriod;
188 int m_contentBytes;
189 time::milliseconds m_contentDelay;
190 std::string m_content;
191 int m_nInterestsReceived;
Spencer Leee7a5b742015-10-29 02:18:11 -0700192 bool m_signWithSha256;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800193
Davide Pesaventod0b59982015-02-27 19:15:15 +0100194 friend class NdnTrafficServer;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800195 };
196
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800197 void
Davide Pesaventod0b59982015-02-27 19:15:15 +0100198 usage() const
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800199 {
Davide Pesaventod0b59982015-02-27 19:15:15 +0100200 std::cout << "Usage:\n"
201 << " " << m_programName << " [options] <Traffic_Configuration_File>\n"
202 << "\n"
203 << "Respond to Interests as per provided Traffic Configuration File.\n"
204 << "Multiple prefixes can be configured for handling.\n"
205 << "Set environment variable NDN_TRAFFIC_LOGFOLDER to redirect output to a log file.\n"
206 << "\n"
207 << "Options:\n"
208 << " [-d interval] - set delay before responding to interest, in milliseconds\n"
209 << " [-c count] - specify maximum number of interests to be satisfied\n"
210 << " [-q] - quiet mode: no interest reception/data generation logging\n"
211 << " [-h] - print this help text and exit\n";
212 exit(EXIT_FAILURE);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800213 }
214
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700215 void
216 setMaximumInterests(int maximumInterests)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800217 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700218 if (maximumInterests < 0)
219 usage();
220 m_nMaximumInterests = maximumInterests;
221 }
222
223 bool
224 hasError() const
225 {
226 return m_hasError;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800227 }
228
229 void
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700230 setContentDelay(int contentDelay)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800231 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700232 if (contentDelay < 0)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800233 usage();
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700234 m_contentDelay = time::milliseconds(contentDelay);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800235 }
236
237 void
Davide Pesaventod0b59982015-02-27 19:15:15 +0100238 setConfigurationFile(const char* configurationFile)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800239 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700240 m_configurationFile = configurationFile;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800241 }
242
243 void
jeraldabraham420dbf02014-04-25 22:58:31 -0700244 setQuietLogging()
245 {
246 m_hasQuietLogging = true;
247 }
248
249 void
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800250 signalHandler()
251 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800252 logStatistics();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100253
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700254 m_logger.shutdownLogger();
255 m_face.shutdown();
Alexander Afanasyev976c3972014-05-26 17:03:40 +0300256 m_ioService.stop();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100257
258 exit(m_hasError ? EXIT_FAILURE : EXIT_SUCCESS);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800259 }
260
261 void
262 logStatistics()
263 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800264 m_logger.log("\n\n== Interest Traffic Report ==\n", false, true);
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700265 m_logger.log("Total Traffic Pattern Types = " +
Spencer Lee8e990232015-11-27 03:54:39 -0700266 to_string(m_trafficPatterns.size()), false, true);
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700267 m_logger.log("Total Interests Received = " +
Spencer Lee8e990232015-11-27 03:54:39 -0700268 to_string(m_nInterestsReceived), false, true);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100269
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700270 if (m_nInterestsReceived < m_nMaximumInterests)
271 m_hasError = true;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100272
273 for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800274 {
Spencer Lee8e990232015-11-27 03:54:39 -0700275 m_logger.log("\nTraffic Pattern Type #" + to_string(patternId + 1), false, true);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700276 m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
Spencer Lee8e990232015-11-27 03:54:39 -0700277 m_logger.log("Total Interests Received = " + to_string(
Davide Pesaventod0b59982015-02-27 19:15:15 +0100278 m_trafficPatterns[patternId].m_nInterestsReceived) + "\n", false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800279 }
280 }
281
282 bool
283 checkTrafficPatternCorrectness()
284 {
285 return true;
286 }
287
288 void
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700289 parseConfigurationFile()
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800290 {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800291 std::string patternLine;
292 std::ifstream patternFile;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700293 m_logger.log("Analyzing Traffic Configuration File: " + m_configurationFile, true, true);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100294
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700295 patternFile.open(m_configurationFile.c_str());
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800296 if (patternFile.is_open())
297 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700298 int lineNumber = 0;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800299 while (getline(patternFile, patternLine))
300 {
301 lineNumber++;
302 if (std::isalpha(patternLine[0]))
303 {
304 DataTrafficConfiguration dataData;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700305 bool shouldSkipLine = false;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800306 if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
307 {
308 while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
309 {
310 lineNumber++;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100311 if (!dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800312 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700313 shouldSkipLine = true;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800314 break;
315 }
316 }
317 lineNumber++;
318 }
319 else
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700320 shouldSkipLine = true;
321 if (!shouldSkipLine)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800322 {
323 if (dataData.checkTrafficDetailCorrectness())
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700324 m_trafficPatterns.push_back(dataData);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800325 }
326 }
327 }
328 patternFile.close();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100329
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800330 if (!checkTrafficPatternCorrectness())
331 {
Davide Pesaventod0b59982015-02-27 19:15:15 +0100332 m_logger.log("ERROR - Traffic Configuration Provided Is Not Proper - " +
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700333 m_configurationFile, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800334 m_logger.shutdownLogger();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100335 exit(EXIT_FAILURE);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800336 }
Davide Pesaventod0b59982015-02-27 19:15:15 +0100337
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800338 m_logger.log("Traffic Configuration File Processing Completed\n", true, false);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100339 for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800340 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700341 m_logger.log("Traffic Pattern Type #" +
Spencer Lee8e990232015-11-27 03:54:39 -0700342 to_string(patternId + 1), false, false);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700343 m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800344 m_logger.log("", false, false);
345 }
346 }
347 else
348 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700349 m_logger.log("ERROR - Unable To Open Traffic Configuration File: " +
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700350 m_configurationFile, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800351 m_logger.shutdownLogger();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100352 exit(EXIT_FAILURE);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800353 }
354 }
355
356 void
357 initializeTrafficConfiguration()
358 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700359 if (boost::filesystem::exists(boost::filesystem::path(m_configurationFile)))
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800360 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700361 if (boost::filesystem::is_regular_file(boost::filesystem::path(m_configurationFile)))
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800362 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700363 parseConfigurationFile();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800364 }
365 else
366 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700367 m_logger.log("ERROR - Traffic Configuration File Is Not A Regular File: " +
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700368 m_configurationFile, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800369 m_logger.shutdownLogger();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100370 exit(EXIT_FAILURE);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800371 }
372 }
373 else
374 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700375 m_logger.log("ERROR - Traffic Configuration File Does Not Exist: " +
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700376 m_configurationFile, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800377 m_logger.shutdownLogger();
Davide Pesaventod0b59982015-02-27 19:15:15 +0100378 exit(EXIT_FAILURE);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800379 }
380 }
381
382 static std::string
Davide Pesaventod0b59982015-02-27 19:15:15 +0100383 getRandomByteString(std::size_t randomSize)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800384 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700385 std::string randomString;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100386 for (std::size_t i = 0; i < randomSize; i++)
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700387 randomString += static_cast<char>(std::rand() % 128);
388 return randomString;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800389 }
390
391 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700392 onInterest(const Name& name, const Interest& interest, int patternId)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800393 {
Spencer Leee7a5b742015-10-29 02:18:11 -0700394 auto& pattern = m_trafficPatterns[patternId];
395
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700396 if (m_nMaximumInterests < 0 || m_nInterestsReceived < m_nMaximumInterests)
397 {
398 Data data(interest.getName());
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800399
Spencer Leee7a5b742015-10-29 02:18:11 -0700400 if (pattern.m_contentType >= 0)
401 data.setContentType(pattern.m_contentType);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700402
Spencer Leee7a5b742015-10-29 02:18:11 -0700403 if (pattern.m_freshnessPeriod >= time::milliseconds(0))
404 data.setFreshnessPeriod(pattern.m_freshnessPeriod);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700405
Davide Pesaventod0b59982015-02-27 19:15:15 +0100406 std::string content;
Spencer Leee7a5b742015-10-29 02:18:11 -0700407 if (pattern.m_contentBytes >= 0)
408 content = getRandomByteString(pattern.m_contentBytes);
409 if (!pattern.m_content.empty())
410 content = pattern.m_content;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700411
412 data.setContent(reinterpret_cast<const uint8_t*>(content.c_str()), content.length());
Spencer Leee7a5b742015-10-29 02:18:11 -0700413
414 if (pattern.m_signWithSha256) {
415 m_keyChain.sign(data, security::signingWithSha256());
416 }
417 else {
418 m_keyChain.sign(data);
419 }
420
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700421 m_nInterestsReceived++;
Spencer Leee7a5b742015-10-29 02:18:11 -0700422 pattern.m_nInterestsReceived++;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100423
424 if (!m_hasQuietLogging) {
425 std::string logLine =
Spencer Lee8e990232015-11-27 03:54:39 -0700426 "Interest Received - PatternType=" + to_string(patternId + 1) +
427 ", GlobalID=" + to_string(m_nInterestsReceived) +
428 ", LocalID=" + to_string(pattern.m_nInterestsReceived) +
Spencer Leee7a5b742015-10-29 02:18:11 -0700429 ", Name=" + pattern.m_name;
jeraldabraham420dbf02014-04-25 22:58:31 -0700430 m_logger.log(logLine, true, false);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100431 }
432
Spencer Leee7a5b742015-10-29 02:18:11 -0700433 if (pattern.m_contentDelay > time::milliseconds(-1))
434 usleep(pattern.m_contentDelay.count() * 1000);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700435 if (m_contentDelay > time::milliseconds(-1))
436 usleep(m_contentDelay.count() * 1000);
437 m_face.put(data);
438 }
439 if (m_nMaximumInterests >= 0 && m_nInterestsReceived == m_nMaximumInterests)
440 {
441 logStatistics();
442 m_logger.shutdownLogger();
443 m_face.shutdown();
Alexander Afanasyev976c3972014-05-26 17:03:40 +0300444 m_ioService.stop();
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700445 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800446 }
447
448 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700449 onRegisterFailed(const ndn::Name& prefix, const std::string& reason, int patternId)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800450 {
Davide Pesaventod0b59982015-02-27 19:15:15 +0100451 std::string logLine;
Spencer Lee8e990232015-11-27 03:54:39 -0700452 logLine += "Prefix Registration Failed - PatternType=" + to_string(patternId + 1);
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700453 logLine += ", Name=" + m_trafficPatterns[patternId].m_name;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800454 m_logger.log(logLine, true, true);
Davide Pesaventod0b59982015-02-27 19:15:15 +0100455
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700456 m_nRegistrationsFailed++;
457 if (m_nRegistrationsFailed == m_trafficPatterns.size())
458 {
459 m_hasError = true;
460 signalHandler();
461 }
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800462 }
463
464 void
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700465 run()
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800466 {
Alexander Afanasyev976c3972014-05-26 17:03:40 +0300467 boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
Alexander Afanasyev740812e2014-10-30 15:37:45 -0700468 signalSet.async_wait(bind(&NdnTrafficServer::signalHandler, this));
Davide Pesaventod0b59982015-02-27 19:15:15 +0100469
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700470 m_logger.initializeLog(m_instanceId);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800471 initializeTrafficConfiguration();
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700472 if (m_nMaximumInterests == 0)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800473 {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700474 logStatistics();
475 m_logger.shutdownLogger();
476 return;
477 }
478
Davide Pesaventod0b59982015-02-27 19:15:15 +0100479 for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++)
480 m_face.setInterestFilter(m_trafficPatterns[patternId].m_name,
481 bind(&NdnTrafficServer::onInterest, this, _1, _2, patternId),
482 bind(&NdnTrafficServer::onRegisterFailed, this, _1, _2, patternId));
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800483
484 try {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700485 m_face.processEvents();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800486 }
Davide Pesaventod0b59982015-02-27 19:15:15 +0100487 catch (const std::exception& e) {
488 m_logger.log("ERROR: " + std::string(e.what()), true, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800489 m_logger.shutdownLogger();
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700490 m_hasError = true;
Alexander Afanasyev976c3972014-05-26 17:03:40 +0300491 m_ioService.stop();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800492 }
493 }
494
495private:
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700496 KeyChain m_keyChain;
Alexander Afanasyev740812e2014-10-30 15:37:45 -0700497 Logger m_logger;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700498 std::string m_programName;
499 bool m_hasError;
jeraldabraham420dbf02014-04-25 22:58:31 -0700500 bool m_hasQuietLogging;
Davide Pesaventod0b59982015-02-27 19:15:15 +0100501 std::size_t m_nRegistrationsFailed;
Alexander Afanasyev740812e2014-10-30 15:37:45 -0700502 int m_nMaximumInterests;
503 int m_nInterestsReceived;
504 time::milliseconds m_contentDelay;
505 std::string m_instanceId;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700506 std::string m_configurationFile;
Alexander Afanasyev740812e2014-10-30 15:37:45 -0700507
Alexander Afanasyev976c3972014-05-26 17:03:40 +0300508 boost::asio::io_service m_ioService;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700509 Face m_face;
510 std::vector<DataTrafficConfiguration> m_trafficPatterns;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800511};
512
513} // namespace ndn
514
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700515int
516main(int argc, char* argv[])
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800517{
Davide Pesaventod0b59982015-02-27 19:15:15 +0100518 std::srand(std::time(nullptr));
519
520 ndn::NdnTrafficServer server(argv[0]);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800521 int option;
jeraldabraham420dbf02014-04-25 22:58:31 -0700522 while ((option = getopt(argc, argv, "hqc:d:")) != -1) {
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800523 switch (option) {
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700524 case 'h':
Davide Pesaventod0b59982015-02-27 19:15:15 +0100525 server.usage();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800526 break;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700527 case 'c':
Davide Pesaventod0b59982015-02-27 19:15:15 +0100528 server.setMaximumInterests(atoi(optarg));
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800529 break;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700530 case 'd':
Davide Pesaventod0b59982015-02-27 19:15:15 +0100531 server.setContentDelay(atoi(optarg));
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700532 break;
jeraldabraham420dbf02014-04-25 22:58:31 -0700533 case 'q':
Davide Pesaventod0b59982015-02-27 19:15:15 +0100534 server.setQuietLogging();
jeraldabraham420dbf02014-04-25 22:58:31 -0700535 break;
jeraldabrahamcc3c6c92014-03-28 02:21:45 -0700536 default:
Davide Pesaventod0b59982015-02-27 19:15:15 +0100537 server.usage();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800538 break;
539 }
540 }
541
542 argc -= optind;
543 argv += optind;
544
Davide Pesaventod0b59982015-02-27 19:15:15 +0100545 if (!argc)
546 server.usage();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800547
Davide Pesaventod0b59982015-02-27 19:15:15 +0100548 server.setConfigurationFile(argv[0]);
549 server.run();
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800550
Davide Pesaventod0b59982015-02-27 19:15:15 +0100551 return server.hasError() ? EXIT_FAILURE : EXIT_SUCCESS;
Spencer Leee7a5b742015-10-29 02:18:11 -0700552}