blob: 0769c693b9c0eff9588f15ec16899e4a2bbcfb3c [file] [log] [blame]
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2014 University of Arizona.
4 *
5 * GNU 3.0 License, see the LICENSE file for more information
6 *
7 * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
8 */
9
10#include <sstream>
11#include <boost/asio.hpp>
12#include <boost/filesystem.hpp>
13
14#include <ndn-cpp-dev/face.hpp>
15#include <ndn-cpp-dev/security/key-chain.hpp>
16
17#include "logger.hpp"
18
19namespace ndn {
20
21class NdnTrafficServer
22{
23public:
Alexander Afanasyevfda32a32014-03-20 10:50:00 -070024 NdnTrafficServer(char* programName)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080025 : m_logger("NDNTrafficServer")
26 , ioService_(new boost::asio::io_service)
27 , face_(ioService_)
28 , keyChain_()
29 {
30 std::srand(std::time(0));
31 instanceId_ = toString(std::rand());
32 programName_ = programName;
33 contentDelayTime_ = getDefaultContentDelayTime();
34 totalRegistrationsFailed_ = 0;
35 configurationFile_ = "";
36 totalInterestReceived_ = 0;
37 }
38
39 class DataTrafficConfiguration
40 {
41 public:
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080042 DataTrafficConfiguration()
43 {
44 name = "";
45 contentType = -1;
46 freshnessPeriod = -1;
47 contentBytes = -1;
48 content = "";
49 totalInterestReceived = 0;
50 }
51
52 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -070053 printTrafficConfiguration(Logger& logger)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080054 {
55 std::string detail;
56 detail = "";
57 if (name != "")
58 detail += "Name="+name+", ";
59 if (contentType >= 0)
60 detail += "ContentType="+toString(contentType)+", ";
61 if (freshnessPeriod >= 0)
62 detail += "FreshnessPeriod="+toString(freshnessPeriod)+", ";
63 if (contentBytes >= 0)
64 detail += "ContentBytes="+toString(contentBytes)+", ";
65 if (content != "")
66 detail += "Content="+content+", ";
67 if (detail.length() >= 2)
68 detail = detail.substr(0, detail.length()-2);
69 logger.log(detail, false, false);
70 }
71
72
73 bool
Alexander Afanasyevfda32a32014-03-20 10:50:00 -070074 extractParameterValue(const std::string& detail,
75 std::string& parameter, std::string& value)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080076 {
77 int i;
78 std::string allowedCharacters = ":/+._-%";
79 parameter = "";
80 value = "";
81 i = 0;
82 while (detail[i] != '=' && i < detail.length())
83 {
84 parameter += detail[i];
85 i++;
86 }
87 if (i == detail.length())
88 return false;
89 i++;
Alexander Afanasyevfda32a32014-03-20 10:50:00 -070090 while ((std::isalnum(detail[i]) ||
91 allowedCharacters.find(detail[i]) != std::string::npos) &&
92 i < detail.length())
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -080093 {
94 value += detail[i];
95 i++;
96 }
97 if(parameter == "" || value == "")
98 return false;
99 return true;
100 }
101
102 bool
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700103 processConfigurationDetail(const std::string& detail,
104 Logger& logger, int lineNumber)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800105 {
106 std::string parameter, value;
107 if (extractParameterValue(detail, parameter, value))
108 {
109 if (parameter == "Name")
110 name = value;
111 else if (parameter == "ContentType")
112 contentType = toInteger(value);
113 else if (parameter == "FreshnessPeriod")
114 freshnessPeriod = toInteger(value);
115 else if (parameter == "ContentBytes")
116 contentBytes = toInteger(value);
117 else if (parameter == "Content")
118 content = value;
119 else
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700120 logger.log("Line "+toString(lineNumber)+
121 " \t- Invalid Parameter='"+parameter+"'", false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800122 }
123 else
124 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700125 logger.log("Line "+toString(lineNumber)+
126 " \t- Improper Traffic Configuration Line- "+detail, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800127 return false;
128 }
129 return true;
130 }
131
132 bool
133 checkTrafficDetailCorrectness()
134 {
135 return true;
136 }
137
138 std::string name;
139 int contentType;
140 int freshnessPeriod;
141 int contentBytes;
142 std::string content;
143 int totalInterestReceived;
144
145 };
146
147 std::string
148 getDefaultContent()
149 {
150 return "";
151 }
152
153 static std::string
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700154 toString(int integerValue)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800155 {
156 std::stringstream stream;
157 stream << integerValue;
158 return stream.str();
159 }
160
161 static int
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700162 toInteger(std::string stringValue)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800163 {
164 int integerValue;
165 std::stringstream stream(stringValue);
166 stream >> integerValue;
167 return integerValue;
168 }
169
170 void
171 usage()
172 {
173
174 std::cout << "\nUsage: " << programName_ << " [options] <Traffic_Configuration_File>\n"
175 "Respond to Interest as per provided Traffic Configuration File\n"
176 "Multiple Prefixes can be configured for handling.\n"
177 "Set environment variable NDN_TRAFFIC_LOGFOLDER for redirecting output to a log.\n"
178 " [-d interval] - set delay before responding to interest in milliseconds (minimum "
179 << getDefaultContentDelayTime() << " milliseconds)\n"
180 " [-h] - print help and exit\n\n";
181 exit(1);
182
183 }
184
185 int
186 getDefaultContentDelayTime()
187 {
188 return 0;
189 }
190
191 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700192 setContentDelayTime(int contentDelayTime)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800193 {
194 if (contentDelayTime < 0)
195 usage();
196 contentDelayTime_ = contentDelayTime;
197 }
198
199 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700200 setConfigurationFile(char* configurationFile)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800201 {
202 configurationFile_ = configurationFile;
203 }
204
205 void
206 signalHandler()
207 {
208 m_logger.shutdownLogger();
209 face_.shutdown();
210 ioService_.reset();
211 logStatistics();
212 exit(1);
213 }
214
215 void
216 logStatistics()
217 {
218 int patternId;
219 m_logger.log("\n\n== Interest Traffic Report ==\n", false, true);
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700220 m_logger.log("Total Traffic Pattern Types = " +
221 toString((int)trafficPattern_.size()), false, true);
222 m_logger.log("Total Interests Received = " +
223 toString(totalInterestReceived_), false, true);
224
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800225 for (patternId=0; patternId<trafficPattern_.size(); patternId++)
226 {
227 m_logger.log("\nTraffic Pattern Type #"+toString(patternId+1), false, true);
228 trafficPattern_[patternId].printTrafficConfiguration(m_logger);
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700229 m_logger.log("Total Interests Received = " +
230 toString(trafficPattern_[patternId].totalInterestReceived)+"\n", false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800231 }
232 }
233
234 bool
235 checkTrafficPatternCorrectness()
236 {
237 return true;
238 }
239
240 void
241 analyzeConfigurationFile()
242 {
243 int patternId;
244 int lineNumber;
245 bool skipLine;
246 std::string patternLine;
247 std::ifstream patternFile;
248 m_logger.log("Analyzing Traffic Configuration File: " + configurationFile_, true, true);
249 patternFile.open(configurationFile_.c_str());
250 if (patternFile.is_open())
251 {
252 patternId = 0;
253 lineNumber = 0;
254 while (getline(patternFile, patternLine))
255 {
256 lineNumber++;
257 if (std::isalpha(patternLine[0]))
258 {
259 DataTrafficConfiguration dataData;
260 skipLine = false;
261 patternId++;
262 if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
263 {
264 while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
265 {
266 lineNumber++;
267 if (!dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
268 {
269 skipLine = true;
270 break;
271 }
272 }
273 lineNumber++;
274 }
275 else
276 skipLine = true;
277 if( !skipLine )
278 {
279 if (dataData.checkTrafficDetailCorrectness())
280 trafficPattern_.push_back(dataData);
281 }
282 }
283 }
284 patternFile.close();
285 if (!checkTrafficPatternCorrectness())
286 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700287 m_logger.log("ERROR - Traffic Configuration Provided Is Not Proper- " +
288 configurationFile_, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800289 m_logger.shutdownLogger();
290 exit(1);
291 }
292 m_logger.log("Traffic Configuration File Processing Completed\n", true, false);
293 for (patternId = 0; patternId < trafficPattern_.size(); patternId++)
294 {
295 m_logger.log("Traffic Pattern Type #"+toString(patternId+1), false, false);
296 trafficPattern_[patternId].printTrafficConfiguration(m_logger);
297 m_logger.log("", false, false);
298 }
299 }
300 else
301 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700302 m_logger.log("ERROR - Unable To Open Traffic Configuration File: " +
303 configurationFile_, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800304 m_logger.shutdownLogger();
305 exit(1);
306 }
307 }
308
309 void
310 initializeTrafficConfiguration()
311 {
312 if (boost::filesystem::exists(boost::filesystem::path(configurationFile_)))
313 {
314 if(boost::filesystem::is_regular_file(boost::filesystem::path(configurationFile_)))
315 {
316 analyzeConfigurationFile();
317 }
318 else
319 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700320 m_logger.log("ERROR - Traffic Configuration File Is Not A Regular File: " +
321 configurationFile_, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800322 m_logger.shutdownLogger();
323 exit(1);
324 }
325 }
326 else
327 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700328 m_logger.log("ERROR - Traffic Configuration File Does Not Exist: " +
329 configurationFile_, false, true);
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800330 m_logger.shutdownLogger();
331 exit(1);
332 }
333 }
334
335 static std::string
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700336 getRandomByteString(int randomSize)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800337 {
338 int i;
339 std::string characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw0123456789";
340 std::string randomData;
341 for (i=0; i<randomSize; i++)
342 randomData += characterSet[std::rand() % characterSet.length()];
343 return randomData;
344 }
345
346 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700347 onInterest(const Name& name, const Interest& interest, int patternId)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800348 {
349 std::string content, logLine;
350 content = "";
351 logLine = "";
352
353 Data data(interest.getName());
354 if (trafficPattern_[patternId].contentType >= 0)
355 data.setContentType(trafficPattern_[patternId].contentType);
356 if (trafficPattern_[patternId].freshnessPeriod >= 0)
jeraldabraham5f61ec22014-03-20 10:41:53 -0700357 data.setFreshnessPeriod(time::milliseconds(trafficPattern_[patternId].freshnessPeriod));
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800358 if (trafficPattern_[patternId].contentBytes >= 0)
359 content = getRandomByteString(trafficPattern_[patternId].contentBytes);
360 if (trafficPattern_[patternId].content != "")
361 content = trafficPattern_[patternId].content;
362 data.setContent((const uint8_t*)content.c_str(), content.length());
363 keyChain_.sign(data);
364 totalInterestReceived_++;
365 trafficPattern_[patternId].totalInterestReceived++;
366 logLine += "Interest Received - PatternType="+toString(patternId+1);
367 logLine += ", GlobalID="+toString(totalInterestReceived_);
368 logLine += ", LocalID="+toString(trafficPattern_[patternId].totalInterestReceived);
369 logLine += ", Name="+trafficPattern_[patternId].name;
370 m_logger.log(logLine, true, false);
371 usleep(contentDelayTime_*1000);
372 face_.put(data);
373 }
374
375 void
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700376 onRegisterFailed(const ndn::Name& prefix, const std::string& reason, int patternId)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800377 {
378 std::string logLine;
379 logLine = "";
380 logLine += "Prefix Registration Failed - PatternType="+toString(patternId+1);
381 logLine += ", Name="+trafficPattern_[patternId].name;
382 m_logger.log(logLine, true, true);
383 totalRegistrationsFailed_++;
384 if (totalRegistrationsFailed_ == trafficPattern_.size())
385 signalHandler();
386 }
387
388 void
389 initialize()
390 {
391 boost::asio::signal_set signalSet(*ioService_, SIGINT, SIGTERM);
392 signalSet.async_wait(boost::bind(&NdnTrafficServer::signalHandler, this));
393 m_logger.initializeLog(instanceId_);
394 initializeTrafficConfiguration();
395
396 int patternId;
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700397 for (patternId=0; patternId<trafficPattern_.size(); patternId++)
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800398 {
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700399 face_.setInterestFilter(trafficPattern_[patternId].name,
400 bind(&NdnTrafficServer::onInterest,
401 this, _1, _2,
402 patternId),
403 bind(&NdnTrafficServer::onRegisterFailed,
404 this, _1, _2,
405 patternId));
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800406 }
407
408 try {
409 face_.processEvents();
410 }
411 catch(std::exception &e) {
412 m_logger.log("ERROR: "+(std::string)e.what(), true, true);
413 m_logger.shutdownLogger();
414 }
415 }
416
417private:
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800418 KeyChain keyChain_;
419 std::string programName_;
420 std::string instanceId_;
421 int contentDelayTime_;
422 int totalRegistrationsFailed_;
423 Logger m_logger;
424 std::string configurationFile_;
425 ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
426 Face face_;
427 std::vector<DataTrafficConfiguration> trafficPattern_;
428 int totalInterestReceived_;
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800429};
430
431} // namespace ndn
432
Alexander Afanasyevfda32a32014-03-20 10:50:00 -0700433int
434main(int argc, char* argv[])
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800435{
436 int option;
437 ndn::NdnTrafficServer ndnTrafficServer (argv[0]);
438 while ((option = getopt(argc, argv, "hd:")) != -1) {
439 switch (option) {
440 case 'h' :
441 ndnTrafficServer.usage();
442 break;
443 case 'd' :
444 ndnTrafficServer.setContentDelayTime(atoi(optarg));
445 break;
446 default :
447 ndnTrafficServer.usage();
448 break;
449 }
450 }
451
452 argc -= optind;
453 argv += optind;
454
455 if (argv[0] == NULL)
456 ndnTrafficServer.usage();
457
458 ndnTrafficServer.setConfigurationFile(argv[0]);
459 ndnTrafficServer.initialize();
460
461 return 0;
462}