blob: f28b5d6097419643994e560eaa2c6f01b321ed6a [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 <string>
9#include <sstream>
10#include <fstream>
11#include <vector>
12#include <boost/asio.hpp>
13#include <boost/filesystem.hpp>
14
15#include <ndn-cpp-dev/face.hpp>
jeraldabrahamf9543a42014-02-11 06:37:34 -070016#include <ndn-cpp-dev/security/key-chain.hpp>
17
18using namespace ndn;
19
jeraldabrahame891ac92014-02-16 11:04:01 -070020class Logger
21{
22public:
23
24 Logger()
25 {
26 logLocation_ = "";
27 }
28
29 void
30 shutdownLogger()
31 {
32 if (logFile_.is_open())
33 logFile_.close();
34 }
35
36 void
37 log( std::string logLine )
38 {
39 if( logLocation_.length() > 0 )
40 {
41 logFile_ << logLine << std::endl;
42 logFile_.flush();
43 }
44 else
45 std::cout << logLine << std::endl;
46 }
47
48 void
49 initializeLog( std::string instanceId )
50 {
51 char* variableValue = std::getenv("NDN_TRAFFIC_LOGFOLDER");
52 std::string logFilename;
53 logLocation_ = "";
54 if (variableValue != NULL)
55 logLocation_ = variableValue;
56 if (boost::filesystem::exists(boost::filesystem::path(logLocation_)))
57 {
58 if (boost::filesystem::is_directory(boost::filesystem::path(logLocation_)))
59 {
60 logFilename = logLocation_+"/NDNTrafficClient_"+instanceId+".log";
61 logFile_.open(logFilename.c_str(), std::ofstream::out | std::ofstream::trunc);
62 if (logFile_.is_open())
63 std::cout << "Log File Initialized: " << logFilename << std::endl;
64 else
65 {
66 std::cout << "ERROR - Unable To Initialize A Log File At: " << logLocation_ << std::endl
67 << "Using Default Output For Logging." << std::endl;
68 logLocation_ = "";
69 }
70 }
71 else
72 {
73 std::cout << "Environment Variable NDN_TRAFFIC_LOGFOLDER Should Be A Folder." << std::endl
74 << "Using Default Output For Logging." << std::endl;
75 logLocation_ = "";
76 }
77 }
78 else
79 {
80 std::cout << "Environment Variable NDN_TRAFFIC_LOGFOLDER Not Set." << std::endl
81 << "Using Default Output For Logging." << std::endl;
82 logLocation_ = "";
83 }
84 }
85
86private:
87
88 std::string logLocation_;
89 std::ofstream logFile_;
90
91};
92
jeraldabrahamf9543a42014-02-11 06:37:34 -070093class NdnTrafficClient
94{
95public:
96
97 NdnTrafficClient( char* programName )
98 {
jeraldabrahame891ac92014-02-16 11:04:01 -070099 std::srand(std::time(0));
100 instanceId_ = toString(std::rand());
jeraldabrahamf9543a42014-02-11 06:37:34 -0700101 programName_ = programName;
102 interestInterval_ = getDefaultInterestInterval();
103 interestCount_ = getDefaultInterestCount();
jeraldabrahamf9543a42014-02-11 06:37:34 -0700104 configurationFile_ = "";
jeraldabrahame891ac92014-02-16 11:04:01 -0700105 ioService_ = ptr_lib::make_shared<boost::asio::io_service>();
106 face_ = Face(ioService_);
jeraldabrahamf9543a42014-02-11 06:37:34 -0700107 }
108
109 NdnTrafficClient()
110 : keyChain_()
111 {
112 }
113
jeraldabrahame891ac92014-02-16 11:04:01 -0700114 class InterestTrafficConfiguration
115 {
116 public:
117
118 InterestTrafficConfiguration()
119 {
120 trafficPercentage = -1;
121 name = "";
122 nameAppendBytes = -1;
123 nameAppendSequenceNumber = -1;
124 minSuffixComponents = -1;
125 maxSuffixComponents = -1;
126 excludeBefore = "";
127 excludeAfter = "";
128 excludeBeforeBytes = -1;
129 excludeAfterBytes = -1;
130 childSelector = -1;
131 mustBeFresh = -1;
132 nonceDuplicationPercentage = -1;
133 scope = -1;
134 interestLifetime = -1;
135 }
136
137 void
138 printTrafficConfiguration( Logger& logger )
139 {
140 std::string detail;
141 detail = "";
142 if (trafficPercentage > 0)
143 detail += "TrafficPercentage="+toString(trafficPercentage)+", ";
144 if (name != "")
145 detail += "Name="+name+", ";
146 if (nameAppendBytes>0)
147 detail += "NameAppendBytes="+toString(nameAppendBytes)+", ";
148 if (nameAppendSequenceNumber>0)
149 detail += "NameAppendSequenceNumber="+toString(nameAppendSequenceNumber)+", ";
150 if (minSuffixComponents>0)
151 detail += "MinSuffixComponents="+toString(minSuffixComponents)+", ";
152 if (maxSuffixComponents>0)
153 detail += "MaxSuffixComponents="+toString(maxSuffixComponents)+", ";
154 if (excludeBefore != "")
155 detail += "ExcludeBefore="+excludeBefore+", ";
156 if (excludeAfter != "")
157 detail += "ExcludeAfter="+excludeAfter+", ";
158 if (excludeBeforeBytes > 0)
159 detail += "ExcludeBeforeBytes="+toString(excludeBeforeBytes)+", ";
160 if (excludeAfterBytes > 0)
161 detail += "ExcludeAfterBytes="+toString(excludeAfterBytes)+", ";
162 if (childSelector > 0)
163 detail += "ChildSelector="+toString(childSelector)+", ";
164 if (mustBeFresh > 0)
165 detail += "MustBeFresh="+toString(mustBeFresh)+", ";
166 if (nonceDuplicationPercentage > 0)
167 detail += "NonceDuplicationPercentage="+toString(nonceDuplicationPercentage)+", ";
168 if (scope > 0)
169 detail += "Scope="+toString(scope)+", ";
170 if (interestLifetime > 0)
171 detail += "InterestLifetime="+toString(interestLifetime)+", ";
172 if (detail.length() >= 0)
173 detail = detail.substr(0, detail.length()-2);
174 logger.log(detail);
175 }
176
177 bool
178 extractParameterValue( std::string detail, std::string& parameter, std::string& value )
179 {
180 int i;
181 std::string allowedCharacters = ":/+._-%";
182 parameter = "";
183 value = "";
184 i = 0;
185 while (detail[i] != '=' && i < detail.length())
186 {
187 parameter += detail[i];
188 i++;
189 }
190 if (i == detail.length())
191 return false;
192 i++;
193 while ((std::isalnum(detail[i]) || allowedCharacters.find(detail[i]) != std::string::npos) && i < detail.length())
194 {
195 value += detail[i];
196 i++;
197 }
198 if(parameter == "" || value == "")
199 return false;
200 return true;
201 }
202
203 bool
204 processConfigurationDetail( std::string detail, Logger& logger, int lineNumber )
205 {
206 std::string parameter, value;
207 if (extractParameterValue(detail, parameter, value))
208 {
209 if (parameter == "TrafficPercentage")
210 trafficPercentage = toInteger(value);
211 else if (parameter == "Name")
212 name = value;
213 else if (parameter == "NameAppendBytes")
214 nameAppendBytes = toInteger(value);
215 else if (parameter == "NameAppendSequenceNumber")
216 nameAppendSequenceNumber = toInteger(value);
217 else if (parameter == "MinSuffixComponents")
218 minSuffixComponents = toInteger(value);
219 else if (parameter == "MaxSuffixComponents")
220 maxSuffixComponents = toInteger(value);
221 else if (parameter == "ExcludeBefore")
222 excludeBefore = value;
223 else if (parameter == "ExcludeAfter")
224 excludeAfter = value;
225 else if (parameter == "ExcludeBeforeBytes")
226 excludeBeforeBytes = toInteger(value);
227 else if (parameter == "ExcludeAfterBytes")
228 excludeAfterBytes = toInteger(value);
229 else if (parameter == "ChildSelector")
230 childSelector = toInteger(value);
231 else if (parameter == "MustBeFresh")
232 mustBeFresh = toInteger(value);
233 else if (parameter == "NonceDuplicationPercentage")
234 nonceDuplicationPercentage = toInteger(value);
235 else if (parameter == "Scope")
236 scope = toInteger(value);
237 else if (parameter == "InterestLifetime")
238 interestLifetime = toInteger(value);
239 else
240 logger.log("Line "+toString(lineNumber)+" \t- Invalid Parameter='"+parameter+"'");
241 }
242 else
243 {
244 logger.log("Line "+toString(lineNumber)+" \t: Improper Traffic Configuration Line- "+detail);
245 return false;
246 }
247 return true;
248 }
249
250 bool
251 checkTrafficDetailCorrectness()
252 {
253 return true;
254 }
255
256 int trafficPercentage;
257 std::string name;
258 int nameAppendBytes;
259 int nameAppendSequenceNumber;
260 int minSuffixComponents;
261 int maxSuffixComponents;
262 std::string excludeBefore;
263 std::string excludeAfter;
264 int excludeBeforeBytes;
265 int excludeAfterBytes;
266 int childSelector;
267 int mustBeFresh;
268 int nonceDuplicationPercentage;
269 int scope;
270 int interestLifetime;
271
272 };
273
274 static std::string
275 toString( int integerValue )
276 {
277 std::stringstream stream;
278 stream << integerValue;
279 return stream.str();
280 }
281
282 static int
283 toInteger( std::string stringValue )
284 {
285 int integerValue;
286 std::stringstream stream(stringValue);
287 stream >> integerValue;
288 return integerValue;
289 }
290
jeraldabrahamf9543a42014-02-11 06:37:34 -0700291 void
292 usage()
293 {
294 std::cout << "\nUsage: " << programName_ << " Printing Usage"
jeraldabrahame891ac92014-02-16 11:04:01 -0700295 << std::endl << std::endl;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700296 exit(1);
297 }
298
299 int
300 getDefaultInterestInterval()
301 {
jeraldabrahame891ac92014-02-16 11:04:01 -0700302 return 1000;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700303 }
304
305 int
306 getDefaultInterestCount()
307 {
308 return -1;
309 }
310
jeraldabrahamf9543a42014-02-11 06:37:34 -0700311 void
312 setInterestInterval( int interestInterval )
313 {
314 if (interestInterval < 0)
315 usage();
316 interestInterval_ = interestInterval;
317 }
318
319 void
320 setInterestCount( int interestCount )
321 {
322 if (interestCount < 0)
323 usage();
324 interestCount_ = interestCount;
325 }
326
327 void
jeraldabrahamf9543a42014-02-11 06:37:34 -0700328 setConfigurationFile( char* configurationFile )
329 {
330 configurationFile_ = configurationFile;
331 }
332
jeraldabrahame891ac92014-02-16 11:04:01 -0700333 void
334 signalHandler()
335 {
336 logger_.shutdownLogger();
337 face_.shutdown();
338 ioService_.reset();
339 exit(1);
340 }
341
342 bool
343 checkTrafficPatternCorrectness()
344 {
345 return true;
346 }
347
348 void
349 analyzeConfigurationFile()
350 {
351 int patternId;
352 int lineNumber;
353 bool skipLine;
354 std::string patternLine;
355 std::ifstream patternFile;
356 logger_.log("Analyzing Traffic Configuration File: " + configurationFile_);
357 patternFile.open(configurationFile_.c_str());
358 if (patternFile.is_open())
359 {
360 patternId = 0;
361 lineNumber = 0;
362 while (getline(patternFile, patternLine))
363 {
364 lineNumber++;
365 if (std::isalpha(patternLine[0]))
366 {
367 InterestTrafficConfiguration interestData;
368 skipLine = false;
369 patternId++;
370 if (interestData.processConfigurationDetail(patternLine, logger_, lineNumber))
371 {
372 while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
373 {
374 lineNumber++;
375 if (!interestData.processConfigurationDetail(patternLine, logger_, lineNumber))
376 {
377 skipLine = true;
378 break;
379 }
380 }
381 lineNumber++;
382 }
383 else
384 skipLine = true;
385 if( !skipLine )
386 {
387 if (interestData.checkTrafficDetailCorrectness())
388 trafficPattern_.push_back(interestData);
389 }
390 }
391 }
392 patternFile.close();
393 if (!checkTrafficPatternCorrectness())
394 {
395 logger_.log("ERROR - Traffic Configuration Provided Is Not Proper- " + configurationFile_);
396 logger_.shutdownLogger();
397 std::cout << "ERROR - Check Log File For Details." << std::endl;
398 exit(1);
399 }
400 for (patternId = 0; patternId < trafficPattern_.size(); patternId++)
401 trafficPattern_[patternId].printTrafficConfiguration(logger_);
402 }
403 else
404 {
405 logger_.log("ERROR - Unable To Open Traffic Configuration File: " + configurationFile_);
406 logger_.shutdownLogger();
407 std::cout << "ERROR - Check Log File For Details." << std::endl;
408 exit(1);
409 }
410 }
411
412 void
413 initializeTrafficConfiguration()
414 {
415 if (boost::filesystem::exists(boost::filesystem::path(configurationFile_)))
416 {
417 if(boost::filesystem::is_regular_file(boost::filesystem::path(configurationFile_)))
418 {
419 analyzeConfigurationFile();
420 }
421 else
422 {
423 logger_.log("ERROR - Traffic Configuration File Is Not A Regular File: " + configurationFile_);
424 logger_.shutdownLogger();
425 std::cout << "ERROR - Check Log File For Details." << std::endl;
426 exit(1);
427 }
428 }
429 else
430 {
431 logger_.log("ERROR - Traffic Configuration File Does Not Exist: " + configurationFile_);
432 logger_.shutdownLogger();
433 std::cout << "ERROR - Check Log File For Details." << std::endl;
434 exit(1);
435 }
436 }
437
438 void
439 initialize()
440 {
441 boost::asio::signal_set signalSet(*ioService_, SIGINT, SIGTERM);
442 signalSet.async_wait(boost::bind(&NdnTrafficClient::signalHandler, this));
443 logger_.initializeLog(instanceId_);
444 initializeTrafficConfiguration();
445 }
446
jeraldabrahamf9543a42014-02-11 06:37:34 -0700447private:
448
449 KeyChain keyChain_;
450 std::string programName_;
jeraldabrahame891ac92014-02-16 11:04:01 -0700451 std::string instanceId_;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700452 int interestInterval_;
453 int interestCount_;
jeraldabrahame891ac92014-02-16 11:04:01 -0700454 Logger logger_;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700455 std::string configurationFile_;
jeraldabrahame891ac92014-02-16 11:04:01 -0700456 ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
457 std::vector<InterestTrafficConfiguration> trafficPattern_;
458 Face face_;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700459
460};
461
462int main( int argc, char* argv[] )
463{
464 int option;
465 NdnTrafficClient ndnTrafficClient (argv[0]);
jeraldabrahame891ac92014-02-16 11:04:01 -0700466 while ((option = getopt(argc, argv, "hi:c:")) != -1) {
jeraldabrahamf9543a42014-02-11 06:37:34 -0700467 switch (option) {
468 case 'h' :
469 ndnTrafficClient.usage();
470 break;
471 case 'i' :
472 ndnTrafficClient.setInterestInterval(atoi(optarg));
473 break;
474 case 'c' :
475 ndnTrafficClient.setInterestCount(atoi(optarg));
476 break;
jeraldabrahamf9543a42014-02-11 06:37:34 -0700477 default :
478 ndnTrafficClient.usage();
479 break;
480 }
481 }
482
483 argc -= optind;
484 argv += optind;
485
jeraldabrahame891ac92014-02-16 11:04:01 -0700486 if (argv[0] == NULL)
jeraldabrahamf9543a42014-02-11 06:37:34 -0700487 ndnTrafficClient.usage();
488
489 ndnTrafficClient.setConfigurationFile(argv[0]);
jeraldabrahame891ac92014-02-16 11:04:01 -0700490 ndnTrafficClient.initialize();
jeraldabrahamf9543a42014-02-11 06:37:34 -0700491
492 return 0;
493}