blob: 5efcb0a4dbcfbc7b9e193e31478ccf26b34b41d9 [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:
24
25 NdnTrafficServer( char* programName )
26 : m_logger("NDNTrafficServer")
27 , ioService_(new boost::asio::io_service)
28 , face_(ioService_)
29 , keyChain_()
30 {
31 std::srand(std::time(0));
32 instanceId_ = toString(std::rand());
33 programName_ = programName;
34 contentDelayTime_ = getDefaultContentDelayTime();
35 totalRegistrationsFailed_ = 0;
36 configurationFile_ = "";
37 totalInterestReceived_ = 0;
38 }
39
40 class DataTrafficConfiguration
41 {
42 public:
43
44 DataTrafficConfiguration()
45 {
46 name = "";
47 contentType = -1;
48 freshnessPeriod = -1;
49 contentBytes = -1;
50 content = "";
51 totalInterestReceived = 0;
52 }
53
54 void
55 printTrafficConfiguration( Logger& logger )
56 {
57 std::string detail;
58 detail = "";
59 if (name != "")
60 detail += "Name="+name+", ";
61 if (contentType >= 0)
62 detail += "ContentType="+toString(contentType)+", ";
63 if (freshnessPeriod >= 0)
64 detail += "FreshnessPeriod="+toString(freshnessPeriod)+", ";
65 if (contentBytes >= 0)
66 detail += "ContentBytes="+toString(contentBytes)+", ";
67 if (content != "")
68 detail += "Content="+content+", ";
69 if (detail.length() >= 2)
70 detail = detail.substr(0, detail.length()-2);
71 logger.log(detail, false, false);
72 }
73
74
75 bool
76 extractParameterValue( std::string detail, std::string& parameter, std::string& value )
77 {
78 int i;
79 std::string allowedCharacters = ":/+._-%";
80 parameter = "";
81 value = "";
82 i = 0;
83 while (detail[i] != '=' && i < detail.length())
84 {
85 parameter += detail[i];
86 i++;
87 }
88 if (i == detail.length())
89 return false;
90 i++;
91 while ((std::isalnum(detail[i]) || allowedCharacters.find(detail[i]) != std::string::npos) && i < detail.length())
92 {
93 value += detail[i];
94 i++;
95 }
96 if(parameter == "" || value == "")
97 return false;
98 return true;
99 }
100
101 bool
102 processConfigurationDetail( std::string detail, Logger& logger, int lineNumber )
103 {
104 std::string parameter, value;
105 if (extractParameterValue(detail, parameter, value))
106 {
107 if (parameter == "Name")
108 name = value;
109 else if (parameter == "ContentType")
110 contentType = toInteger(value);
111 else if (parameter == "FreshnessPeriod")
112 freshnessPeriod = toInteger(value);
113 else if (parameter == "ContentBytes")
114 contentBytes = toInteger(value);
115 else if (parameter == "Content")
116 content = value;
117 else
118 logger.log("Line "+toString(lineNumber)+" \t- Invalid Parameter='"+parameter+"'", false, true);
119 }
120 else
121 {
122 logger.log("Line "+toString(lineNumber)+" \t- Improper Traffic Configuration Line- "+detail, false, true);
123 return false;
124 }
125 return true;
126 }
127
128 bool
129 checkTrafficDetailCorrectness()
130 {
131 return true;
132 }
133
134 std::string name;
135 int contentType;
136 int freshnessPeriod;
137 int contentBytes;
138 std::string content;
139 int totalInterestReceived;
140
141 };
142
143 std::string
144 getDefaultContent()
145 {
146 return "";
147 }
148
149 static std::string
150 toString( int integerValue )
151 {
152 std::stringstream stream;
153 stream << integerValue;
154 return stream.str();
155 }
156
157 static int
158 toInteger( std::string stringValue )
159 {
160 int integerValue;
161 std::stringstream stream(stringValue);
162 stream >> integerValue;
163 return integerValue;
164 }
165
166 void
167 usage()
168 {
169
170 std::cout << "\nUsage: " << programName_ << " [options] <Traffic_Configuration_File>\n"
171 "Respond to Interest as per provided Traffic Configuration File\n"
172 "Multiple Prefixes can be configured for handling.\n"
173 "Set environment variable NDN_TRAFFIC_LOGFOLDER for redirecting output to a log.\n"
174 " [-d interval] - set delay before responding to interest in milliseconds (minimum "
175 << getDefaultContentDelayTime() << " milliseconds)\n"
176 " [-h] - print help and exit\n\n";
177 exit(1);
178
179 }
180
181 int
182 getDefaultContentDelayTime()
183 {
184 return 0;
185 }
186
187 void
188 setContentDelayTime( int contentDelayTime )
189 {
190 if (contentDelayTime < 0)
191 usage();
192 contentDelayTime_ = contentDelayTime;
193 }
194
195 void
196 setConfigurationFile( char* configurationFile )
197 {
198 configurationFile_ = configurationFile;
199 }
200
201 void
202 signalHandler()
203 {
204 m_logger.shutdownLogger();
205 face_.shutdown();
206 ioService_.reset();
207 logStatistics();
208 exit(1);
209 }
210
211 void
212 logStatistics()
213 {
214 int patternId;
215 m_logger.log("\n\n== Interest Traffic Report ==\n", false, true);
216 m_logger.log("Total Traffic Pattern Types = "+toString((int)trafficPattern_.size()), false, true);
217 m_logger.log("Total Interests Received = "+toString(totalInterestReceived_), false, true);
218 for (patternId=0; patternId<trafficPattern_.size(); patternId++)
219 {
220 m_logger.log("\nTraffic Pattern Type #"+toString(patternId+1), false, true);
221 trafficPattern_[patternId].printTrafficConfiguration(m_logger);
222 m_logger.log("Total Interests Received = "+toString(trafficPattern_[patternId].totalInterestReceived)+"\n", false, true);
223 }
224 }
225
226 bool
227 checkTrafficPatternCorrectness()
228 {
229 return true;
230 }
231
232 void
233 analyzeConfigurationFile()
234 {
235 int patternId;
236 int lineNumber;
237 bool skipLine;
238 std::string patternLine;
239 std::ifstream patternFile;
240 m_logger.log("Analyzing Traffic Configuration File: " + configurationFile_, true, true);
241 patternFile.open(configurationFile_.c_str());
242 if (patternFile.is_open())
243 {
244 patternId = 0;
245 lineNumber = 0;
246 while (getline(patternFile, patternLine))
247 {
248 lineNumber++;
249 if (std::isalpha(patternLine[0]))
250 {
251 DataTrafficConfiguration dataData;
252 skipLine = false;
253 patternId++;
254 if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
255 {
256 while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
257 {
258 lineNumber++;
259 if (!dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
260 {
261 skipLine = true;
262 break;
263 }
264 }
265 lineNumber++;
266 }
267 else
268 skipLine = true;
269 if( !skipLine )
270 {
271 if (dataData.checkTrafficDetailCorrectness())
272 trafficPattern_.push_back(dataData);
273 }
274 }
275 }
276 patternFile.close();
277 if (!checkTrafficPatternCorrectness())
278 {
279 m_logger.log("ERROR - Traffic Configuration Provided Is Not Proper- " + configurationFile_, false, true);
280 m_logger.shutdownLogger();
281 exit(1);
282 }
283 m_logger.log("Traffic Configuration File Processing Completed\n", true, false);
284 for (patternId = 0; patternId < trafficPattern_.size(); patternId++)
285 {
286 m_logger.log("Traffic Pattern Type #"+toString(patternId+1), false, false);
287 trafficPattern_[patternId].printTrafficConfiguration(m_logger);
288 m_logger.log("", false, false);
289 }
290 }
291 else
292 {
293 m_logger.log("ERROR - Unable To Open Traffic Configuration File: " + configurationFile_, false, true);
294 m_logger.shutdownLogger();
295 exit(1);
296 }
297 }
298
299 void
300 initializeTrafficConfiguration()
301 {
302 if (boost::filesystem::exists(boost::filesystem::path(configurationFile_)))
303 {
304 if(boost::filesystem::is_regular_file(boost::filesystem::path(configurationFile_)))
305 {
306 analyzeConfigurationFile();
307 }
308 else
309 {
310 m_logger.log("ERROR - Traffic Configuration File Is Not A Regular File: " + configurationFile_, false, true);
311 m_logger.shutdownLogger();
312 exit(1);
313 }
314 }
315 else
316 {
317 m_logger.log("ERROR - Traffic Configuration File Does Not Exist: " + configurationFile_, false, true);
318 m_logger.shutdownLogger();
319 exit(1);
320 }
321 }
322
323 static std::string
324 getRandomByteString( int randomSize )
325 {
326 int i;
327 std::string characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw0123456789";
328 std::string randomData;
329 for (i=0; i<randomSize; i++)
330 randomData += characterSet[std::rand() % characterSet.length()];
331 return randomData;
332 }
333
334 void
335 onInterest( const Name& name, const Interest& interest, int patternId )
336 {
337 std::string content, logLine;
338 content = "";
339 logLine = "";
340
341 Data data(interest.getName());
342 if (trafficPattern_[patternId].contentType >= 0)
343 data.setContentType(trafficPattern_[patternId].contentType);
344 if (trafficPattern_[patternId].freshnessPeriod >= 0)
jeraldabraham5f61ec22014-03-20 10:41:53 -0700345 data.setFreshnessPeriod(time::milliseconds(trafficPattern_[patternId].freshnessPeriod));
Alexander Afanasyeva8f2a922014-02-26 14:21:56 -0800346 if (trafficPattern_[patternId].contentBytes >= 0)
347 content = getRandomByteString(trafficPattern_[patternId].contentBytes);
348 if (trafficPattern_[patternId].content != "")
349 content = trafficPattern_[patternId].content;
350 data.setContent((const uint8_t*)content.c_str(), content.length());
351 keyChain_.sign(data);
352 totalInterestReceived_++;
353 trafficPattern_[patternId].totalInterestReceived++;
354 logLine += "Interest Received - PatternType="+toString(patternId+1);
355 logLine += ", GlobalID="+toString(totalInterestReceived_);
356 logLine += ", LocalID="+toString(trafficPattern_[patternId].totalInterestReceived);
357 logLine += ", Name="+trafficPattern_[patternId].name;
358 m_logger.log(logLine, true, false);
359 usleep(contentDelayTime_*1000);
360 face_.put(data);
361 }
362
363 void
364 onRegisterFailed( const ndn::Name& prefix, const std::string& reason, int patternId )
365 {
366 std::string logLine;
367 logLine = "";
368 logLine += "Prefix Registration Failed - PatternType="+toString(patternId+1);
369 logLine += ", Name="+trafficPattern_[patternId].name;
370 m_logger.log(logLine, true, true);
371 totalRegistrationsFailed_++;
372 if (totalRegistrationsFailed_ == trafficPattern_.size())
373 signalHandler();
374 }
375
376 void
377 initialize()
378 {
379 boost::asio::signal_set signalSet(*ioService_, SIGINT, SIGTERM);
380 signalSet.async_wait(boost::bind(&NdnTrafficServer::signalHandler, this));
381 m_logger.initializeLog(instanceId_);
382 initializeTrafficConfiguration();
383
384 int patternId;
385 for (patternId=0; patternId<trafficPattern_.size(); patternId++ )
386 {
387 face_.setInterestFilter( trafficPattern_[patternId].name,
388 func_lib::bind( &NdnTrafficServer::onInterest,
389 this, _1, _2,
390 patternId),
391 func_lib::bind( &NdnTrafficServer::onRegisterFailed,
392 this, _1, _2,
393 patternId));
394 }
395
396 try {
397 face_.processEvents();
398 }
399 catch(std::exception &e) {
400 m_logger.log("ERROR: "+(std::string)e.what(), true, true);
401 m_logger.shutdownLogger();
402 }
403 }
404
405private:
406
407 KeyChain keyChain_;
408 std::string programName_;
409 std::string instanceId_;
410 int contentDelayTime_;
411 int totalRegistrationsFailed_;
412 Logger m_logger;
413 std::string configurationFile_;
414 ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
415 Face face_;
416 std::vector<DataTrafficConfiguration> trafficPattern_;
417 int totalInterestReceived_;
418
419};
420
421} // namespace ndn
422
423int main( int argc, char* argv[] )
424{
425 int option;
426 ndn::NdnTrafficServer ndnTrafficServer (argv[0]);
427 while ((option = getopt(argc, argv, "hd:")) != -1) {
428 switch (option) {
429 case 'h' :
430 ndnTrafficServer.usage();
431 break;
432 case 'd' :
433 ndnTrafficServer.setContentDelayTime(atoi(optarg));
434 break;
435 default :
436 ndnTrafficServer.usage();
437 break;
438 }
439 }
440
441 argc -= optind;
442 argv += optind;
443
444 if (argv[0] == NULL)
445 ndnTrafficServer.usage();
446
447 ndnTrafficServer.setConfigurationFile(argv[0]);
448 ndnTrafficServer.initialize();
449
450 return 0;
451}