blob: 38b3461f9ff636368ff62be1465a40fcbf49cb61 [file] [log] [blame]
jeraldabrahamf9543a42014-02-11 06:37:34 -07001/**
2 *
jeraldabrahame891ac92014-02-16 11:04:01 -07003 * Copyright (C) 2014 University of Arizona.
jeraldabrahamf9543a42014-02-11 06:37:34 -07004 * @author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
5 *
6 */
7
jeraldabrahame891ac92014-02-16 11:04:01 -07008#include <sstream>
9#include <boost/asio.hpp>
10#include <boost/filesystem.hpp>
11
12#include <ndn-cpp-dev/face.hpp>
jeraldabrahamf9543a42014-02-11 06:37:34 -070013#include <ndn-cpp-dev/security/key-chain.hpp>
14
15using namespace ndn;
16
jeraldabraham89a58422014-02-18 14:27:14 -070017class Logger
18{
19public:
20
21 Logger()
22 {
23 logLocation_ = "";
24 }
25
26 void
27 shutdownLogger()
28 {
29 if (logFile_.is_open())
30 {
31 log("Terminating Logging Operations" , true, true);
32 logFile_.close();
33 }
34 }
35
36 static std::string
37 getTimestamp()
38 {
39 boost::posix_time::ptime now;
40 now = boost::posix_time::second_clock::local_time();
41 return to_simple_string(now);
42 }
43
44 void
45 log( std::string logLine, bool printTime, bool printToConsole )
46 {
47 if( logLocation_.length() > 0 )
48 {
49 if (printTime)
50 logFile_ << getTimestamp() << " - ";
51 logFile_ << logLine << std::endl;
52 logFile_.flush();
53 if (printToConsole)
54 {
55 if (printTime)
56 std::cout << getTimestamp() << " - ";
57 std::cout << logLine << std::endl;
58 }
59 }
60 else
61 {
62 if (printTime)
63 std::cout << getTimestamp() << " - ";
64 std::cout << logLine << std::endl;
65 }
66 }
67
68 void
69 initializeLog( std::string instanceId )
70 {
71 char* variableValue = std::getenv("NDN_TRAFFIC_LOGFOLDER");
72 std::string logFilename;
73 logLocation_ = "";
74 if (variableValue != NULL)
75 logLocation_ = variableValue;
76 if (boost::filesystem::exists(boost::filesystem::path(logLocation_)))
77 {
78 if (boost::filesystem::is_directory(boost::filesystem::path(logLocation_)))
79 {
80 logFilename = logLocation_+"/NDNTrafficServer_"+instanceId+".log";
81 logFile_.open(logFilename.c_str(), std::ofstream::out | std::ofstream::trunc);
82 if (logFile_.is_open())
83 std::cout << "Log File Initialized: " << logFilename << std::endl;
84 else
85 {
86 std::cout << "ERROR - Unable To Initialize A Log File At: " << logLocation_ << std::endl
87 << "Using Default Output For Logging." << std::endl;
88 logLocation_ = "";
89 }
90 }
91 else
92 {
93 std::cout << "Environment Variable NDN_TRAFFIC_LOGFOLDER Should Be A Folder." << std::endl
94 << "Using Default Output For Logging." << std::endl;
95 logLocation_ = "";
96 }
97 }
98 else
99 {
100 std::cout << "Environment Variable NDN_TRAFFIC_LOGFOLDER Not Set." << std::endl
101 << "Using Default Output For Logging." << std::endl;
102 logLocation_ = "";
103 }
104 }
105
106private:
107
108 std::string logLocation_;
109 std::ofstream logFile_;
110
111};
112
113
jeraldabrahamf9543a42014-02-11 06:37:34 -0700114class NdnTrafficServer
115{
116public:
117
jeraldabraham89a58422014-02-18 14:27:14 -0700118 NdnTrafficServer( char* programName ) : ioService_(new boost::asio::io_service), face_(ioService_), keyChain_()
jeraldabrahamf9543a42014-02-11 06:37:34 -0700119 {
jeraldabrahame891ac92014-02-16 11:04:01 -0700120 std::srand(std::time(0));
jeraldabraham89a58422014-02-18 14:27:14 -0700121 instanceId_ = toString(std::rand());
jeraldabrahamf9543a42014-02-11 06:37:34 -0700122 programName_ = programName;
123 contentDelayTime_ = getDefaultContentDelayTime();
jeraldabraham89a58422014-02-18 14:27:14 -0700124 totalRegistrationsFailed_ = 0;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700125 configurationFile_ = "";
jeraldabraham89a58422014-02-18 14:27:14 -0700126 totalInterestReceived_ = 0;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700127 }
128
jeraldabraham89a58422014-02-18 14:27:14 -0700129 class DataTrafficConfiguration
jeraldabrahamf9543a42014-02-11 06:37:34 -0700130 {
jeraldabraham89a58422014-02-18 14:27:14 -0700131 public:
132
133 DataTrafficConfiguration()
134 {
135 name = "";
136 contentType = -1;
137 freshnessPeriod = -1;
138 contentBytes = -1;
139 content = "";
140 totalInterestReceived = 0;
141 }
142
143 void
144 printTrafficConfiguration( Logger& logger )
145 {
146 std::string detail;
147 detail = "";
148 if (name != "")
149 detail += "Name="+name+", ";
150 if (contentType >= 0)
151 detail += "ContentType="+toString(contentType)+", ";
152 if (freshnessPeriod >= 0)
153 detail += "FreshnessPeriod="+toString(freshnessPeriod)+", ";
154 if (contentBytes >= 0)
155 detail += "ContentBytes="+toString(contentBytes)+", ";
156 if (content != "")
157 detail += "Content="+content+", ";
158 if (detail.length() >= 0)
159 detail = detail.substr(0, detail.length()-2);
160 logger.log(detail, false, false);
161 }
162
163
164 bool
165 extractParameterValue( std::string detail, std::string& parameter, std::string& value )
166 {
167 int i;
168 std::string allowedCharacters = ":/+._-%";
169 parameter = "";
170 value = "";
171 i = 0;
172 while (detail[i] != '=' && i < detail.length())
173 {
174 parameter += detail[i];
175 i++;
176 }
177 if (i == detail.length())
178 return false;
179 i++;
180 while ((std::isalnum(detail[i]) || allowedCharacters.find(detail[i]) != std::string::npos) && i < detail.length())
181 {
182 value += detail[i];
183 i++;
184 }
185 if(parameter == "" || value == "")
186 return false;
187 return true;
188 }
189
190 bool
191 processConfigurationDetail( std::string detail, Logger& logger, int lineNumber )
192 {
193 std::string parameter, value;
194 if (extractParameterValue(detail, parameter, value))
195 {
196 if (parameter == "Name")
197 name = value;
198 else if (parameter == "ContentType")
199 contentType = toInteger(value);
200 else if (parameter == "FreshnessPeriod")
201 freshnessPeriod = toInteger(value);
202 else if (parameter == "ContentBytes")
203 contentBytes = toInteger(value);
204 else if (parameter == "Content")
205 content = value;
206 else
207 logger.log("Line "+toString(lineNumber)+" \t- Invalid Parameter='"+parameter+"'", false, true);
208 }
209 else
210 {
211 logger.log("Line "+toString(lineNumber)+" \t- Improper Traffic Configuration Line- "+detail, false, true);
212 return false;
213 }
214 return true;
215 }
216
217 bool
218 checkTrafficDetailCorrectness()
219 {
220 return true;
221 }
222
223 std::string name;
224 int contentType;
225 int freshnessPeriod;
226 int contentBytes;
227 std::string content;
228 int totalInterestReceived;
229
230 };
231
232 std::string
233 getDefaultContent()
234 {
235 return "";
236 }
237
238 static std::string
239 toString( int integerValue )
240 {
241 std::stringstream stream;
242 stream << integerValue;
243 return stream.str();
244 }
245
246 static int
247 toInteger( std::string stringValue )
248 {
249 int integerValue;
250 std::stringstream stream(stringValue);
251 stream >> integerValue;
252 return integerValue;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700253 }
254
255 void
256 usage()
257 {
jeraldabrahambd241fe2014-02-19 11:39:09 -0700258
259 std::cout << "\nUsage: " << programName_ << " [options] <Traffic_Configuration_File>\n"
260 "Respond to Interest as per provided Traffic Configuration File\n"
261 "Multiple Prefixes can be configured for handling.\n"
262 "Set environment variable NDN_TRAFFIC_LOGFOLDER for redirecting output to a log.\n"
263 " [-d interval] - set delay before responding to interest in milliseconds (minimum "
264 << getDefaultContentDelayTime() << " milliseconds)\n"
265 " [-h] - print help and exit\n\n";
jeraldabrahamf9543a42014-02-11 06:37:34 -0700266 exit(1);
jeraldabrahambd241fe2014-02-19 11:39:09 -0700267
jeraldabrahamf9543a42014-02-11 06:37:34 -0700268 }
269
270 int
271 getDefaultContentDelayTime()
272 {
273 return 0;
274 }
275
jeraldabrahamf9543a42014-02-11 06:37:34 -0700276 void
277 setContentDelayTime( int contentDelayTime )
278 {
279 if (contentDelayTime < 0)
280 usage();
281 contentDelayTime_ = contentDelayTime;
282 }
283
284 void
jeraldabrahamf9543a42014-02-11 06:37:34 -0700285 setConfigurationFile( char* configurationFile )
286 {
287 configurationFile_ = configurationFile;
288 }
289
jeraldabrahame891ac92014-02-16 11:04:01 -0700290 void
291 signalHandler()
292 {
jeraldabraham89a58422014-02-18 14:27:14 -0700293 logger_.shutdownLogger();
jeraldabrahame891ac92014-02-16 11:04:01 -0700294 face_.shutdown();
295 ioService_.reset();
jeraldabraham89a58422014-02-18 14:27:14 -0700296 logStatistics();
jeraldabrahame891ac92014-02-16 11:04:01 -0700297 exit(1);
298 }
299
300 void
jeraldabraham89a58422014-02-18 14:27:14 -0700301 logStatistics()
jeraldabrahame891ac92014-02-16 11:04:01 -0700302 {
jeraldabraham89a58422014-02-18 14:27:14 -0700303 int patternId;
304 logger_.log("\n\n== Interest Traffic Report ==\n", false, true);
305 logger_.log("Total Traffic Pattern Types = "+toString((int)trafficPattern_.size()), false, true);
306 logger_.log("Total Interests Received = "+toString(totalInterestReceived_), false, true);
307 for (patternId=0; patternId<trafficPattern_.size(); patternId++)
jeraldabrahame891ac92014-02-16 11:04:01 -0700308 {
jeraldabraham89a58422014-02-18 14:27:14 -0700309 logger_.log("\nTraffic Pattern Type #"+toString(patternId+1), false, true);
310 trafficPattern_[patternId].printTrafficConfiguration(logger_);
311 logger_.log("Total Interests Received = "+toString(trafficPattern_[patternId].totalInterestReceived)+"\n", false, true);
312 }
313 }
314
315 bool
316 checkTrafficPatternCorrectness()
317 {
318 return true;
319 }
320
321 void
322 analyzeConfigurationFile()
323 {
324 int patternId;
325 int lineNumber;
326 bool skipLine;
327 std::string patternLine;
328 std::ifstream patternFile;
329 logger_.log("Analyzing Traffic Configuration File: " + configurationFile_, true, true);
330 patternFile.open(configurationFile_.c_str());
331 if (patternFile.is_open())
332 {
333 patternId = 0;
334 lineNumber = 0;
335 while (getline(patternFile, patternLine))
jeraldabrahame891ac92014-02-16 11:04:01 -0700336 {
jeraldabraham89a58422014-02-18 14:27:14 -0700337 lineNumber++;
338 if (std::isalpha(patternLine[0]))
339 {
340 DataTrafficConfiguration dataData;
341 skipLine = false;
342 patternId++;
343 if (dataData.processConfigurationDetail(patternLine, logger_, lineNumber))
344 {
345 while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
346 {
347 lineNumber++;
348 if (!dataData.processConfigurationDetail(patternLine, logger_, lineNumber))
349 {
350 skipLine = true;
351 break;
352 }
353 }
354 lineNumber++;
355 }
356 else
357 skipLine = true;
358 if( !skipLine )
359 {
360 if (dataData.checkTrafficDetailCorrectness())
361 trafficPattern_.push_back(dataData);
362 }
363 }
jeraldabrahame891ac92014-02-16 11:04:01 -0700364 }
jeraldabraham89a58422014-02-18 14:27:14 -0700365 patternFile.close();
366 if (!checkTrafficPatternCorrectness())
jeraldabrahame891ac92014-02-16 11:04:01 -0700367 {
jeraldabraham89a58422014-02-18 14:27:14 -0700368 logger_.log("ERROR - Traffic Configuration Provided Is Not Proper- " + configurationFile_, false, true);
369 logger_.shutdownLogger();
370 exit(1);
371 }
372 logger_.log("Traffic Configuration File Processing Completed\n", true, false);
373 for (patternId = 0; patternId < trafficPattern_.size(); patternId++)
374 {
375 logger_.log("Traffic Pattern Type #"+toString(patternId+1), false, false);
376 trafficPattern_[patternId].printTrafficConfiguration(logger_);
377 logger_.log("", false, false);
jeraldabrahame891ac92014-02-16 11:04:01 -0700378 }
379 }
380 else
381 {
jeraldabraham89a58422014-02-18 14:27:14 -0700382 logger_.log("ERROR - Unable To Open Traffic Configuration File: " + configurationFile_, false, true);
383 logger_.shutdownLogger();
384 exit(1);
jeraldabrahame891ac92014-02-16 11:04:01 -0700385 }
386 }
387
388 void
389 initializeTrafficConfiguration()
390 {
jeraldabraham89a58422014-02-18 14:27:14 -0700391 if (boost::filesystem::exists(boost::filesystem::path(configurationFile_)))
392 {
393 if(boost::filesystem::is_regular_file(boost::filesystem::path(configurationFile_)))
394 {
395 analyzeConfigurationFile();
396 }
397 else
398 {
399 logger_.log("ERROR - Traffic Configuration File Is Not A Regular File: " + configurationFile_, false, true);
400 logger_.shutdownLogger();
401 exit(1);
402 }
403 }
404 else
405 {
406 logger_.log("ERROR - Traffic Configuration File Does Not Exist: " + configurationFile_, false, true);
407 logger_.shutdownLogger();
408 exit(1);
409 }
410 }
411
412 static std::string
413 getRandomByteString( int randomSize )
414 {
415 int i;
416 std::string characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw0123456789";
417 std::string randomData;
418 for (i=0; i<randomSize; i++)
419 randomData += characterSet[std::rand() % characterSet.length()];
420 return randomData;
421 }
422
423 void
424 onInterest( const Name& name, const Interest& interest, int patternId )
425 {
426 std::string content, logLine;
427 content = "";
428 logLine = "";
jeraldabrahambd241fe2014-02-19 11:39:09 -0700429
jeraldabraham89a58422014-02-18 14:27:14 -0700430 Data data(interest.getName());
431 if (trafficPattern_[patternId].contentType >= 0)
432 data.setContentType(trafficPattern_[patternId].contentType);
433 if (trafficPattern_[patternId].freshnessPeriod >= 0)
434 data.setFreshnessPeriod(trafficPattern_[patternId].freshnessPeriod);
435 if (trafficPattern_[patternId].contentBytes >= 0)
436 content = getRandomByteString(trafficPattern_[patternId].contentBytes);
437 if (trafficPattern_[patternId].content != "")
438 content = trafficPattern_[patternId].content;
439 data.setContent((const uint8_t*)content.c_str(), content.length());
440 keyChain_.sign(data);
441 totalInterestReceived_++;
442 trafficPattern_[patternId].totalInterestReceived++;
jeraldabrahamb735e8d2014-02-19 09:16:35 -0700443 logLine += "Interest Received - PatternType="+toString(patternId+1);
jeraldabraham89a58422014-02-18 14:27:14 -0700444 logLine += ", GlobalID="+toString(totalInterestReceived_);
445 logLine += ", LocalID="+toString(trafficPattern_[patternId].totalInterestReceived);
446 logLine += ", Name="+trafficPattern_[patternId].name;
447 logger_.log(logLine, true, false);
jeraldabrahambd241fe2014-02-19 11:39:09 -0700448 usleep(contentDelayTime_*1000);
jeraldabraham89a58422014-02-18 14:27:14 -0700449 face_.put(data);
450 }
451
452 void
453 onRegisterFailed( const ndn::Name& prefix, const std::string& reason, int patternId )
454 {
455 std::string logLine;
456 logLine = "";
jeraldabrahamb735e8d2014-02-19 09:16:35 -0700457 logLine += "Prefix Registration Failed - PatternType="+toString(patternId+1);
jeraldabraham89a58422014-02-18 14:27:14 -0700458 logLine += ", Name="+trafficPattern_[patternId].name;
459 logger_.log(logLine, true, true);
460 totalRegistrationsFailed_++;
461 if (totalRegistrationsFailed_ == trafficPattern_.size())
462 signalHandler();
jeraldabrahame891ac92014-02-16 11:04:01 -0700463 }
464
465 void
466 initialize()
467 {
468 boost::asio::signal_set signalSet(*ioService_, SIGINT, SIGTERM);
469 signalSet.async_wait(boost::bind(&NdnTrafficServer::signalHandler, this));
jeraldabraham89a58422014-02-18 14:27:14 -0700470 logger_.initializeLog(instanceId_);
jeraldabrahame891ac92014-02-16 11:04:01 -0700471 initializeTrafficConfiguration();
jeraldabraham89a58422014-02-18 14:27:14 -0700472
473 int patternId;
474 for (patternId=0; patternId<trafficPattern_.size(); patternId++ )
475 {
476 face_.setInterestFilter( trafficPattern_[patternId].name,
477 func_lib::bind( &NdnTrafficServer::onInterest,
478 this, _1, _2,
479 patternId),
480 func_lib::bind( &NdnTrafficServer::onRegisterFailed,
481 this, _1, _2,
482 patternId));
483 }
484
485 try {
486 face_.processEvents();
487 }
488 catch(std::exception &e) {
489 logger_.log("ERROR: "+(std::string)e.what(), true, true);
490 logger_.shutdownLogger();
491 }
jeraldabrahame891ac92014-02-16 11:04:01 -0700492 }
493
jeraldabrahamf9543a42014-02-11 06:37:34 -0700494private:
495
496 KeyChain keyChain_;
497 std::string programName_;
jeraldabraham89a58422014-02-18 14:27:14 -0700498 std::string instanceId_;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700499 int contentDelayTime_;
jeraldabraham89a58422014-02-18 14:27:14 -0700500 int totalRegistrationsFailed_;
501 Logger logger_;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700502 std::string configurationFile_;
jeraldabrahame891ac92014-02-16 11:04:01 -0700503 ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
504 Face face_;
jeraldabraham89a58422014-02-18 14:27:14 -0700505 std::vector<DataTrafficConfiguration> trafficPattern_;
506 int totalInterestReceived_;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700507
508};
509
510int main( int argc, char* argv[] )
511{
512 int option;
513 NdnTrafficServer ndnTrafficServer (argv[0]);
jeraldabrahame891ac92014-02-16 11:04:01 -0700514 while ((option = getopt(argc, argv, "hd:")) != -1) {
jeraldabrahamf9543a42014-02-11 06:37:34 -0700515 switch (option) {
516 case 'h' :
517 ndnTrafficServer.usage();
518 break;
519 case 'd' :
520 ndnTrafficServer.setContentDelayTime(atoi(optarg));
521 break;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700522 default :
523 ndnTrafficServer.usage();
524 break;
525 }
526 }
527
528 argc -= optind;
529 argv += optind;
530
jeraldabrahame891ac92014-02-16 11:04:01 -0700531 if (argv[0] == NULL)
jeraldabrahamf9543a42014-02-11 06:37:34 -0700532 ndnTrafficServer.usage();
533
534 ndnTrafficServer.setConfigurationFile(argv[0]);
jeraldabrahame891ac92014-02-16 11:04:01 -0700535 ndnTrafficServer.initialize();
jeraldabrahamf9543a42014-02-11 06:37:34 -0700536
537 return 0;
538}