blob: fb6cb969c80e5364929b2f90a9edb19a129f3fab [file] [log] [blame]
Hila Ben Abrahame8c22e92016-10-20 14:30:32 -05001/**
2 * This program is used by test_nack interation test.
3 * The program implements a simple consumer that sends one or
4 * two interests and prints the network response (timeout, data or nack).
5 * ndnpeek is not sufficient since it does not allow verifying
6 * the nonces as required by the test.
7 */
8
9#include <boost/asio.hpp>
10#include <ndn-cxx/face.hpp>
11
12namespace ndn {
13
14class TestNackConsumer : boost::noncopyable
15{
16public:
17 explicit
18 TestNackConsumer(const char* programName)
19 : m_programName(programName)
20 , m_face(m_ioService)
21 , m_interestLifetime(time::milliseconds(4000))
22 , m_secondInterestInterval(time::milliseconds(0))
23 {
24 m_nonce1 = static_cast<uint32_t>(std::rand());
25 m_nonce2 = static_cast<uint32_t>(std::rand());
26 }
27
28 void
29 usage() const
30 {
31 std::cout << "Usage:\n"
32 << " " << m_programName
33 << " -p <name> -w <wait_before_quit> [-r second_Interest_interval] \n"
34 << "\n"
35 << " -p <name> Interest prefix\n"
36 << " -w <wait_before_quit> - wait time(ms) before exit\n"
37 << "\n"
38 << "Options:\n"
39 << " [-r second_Interest_interval] - set the time (ms) between first and second Interests\n"
40 << " [-h] - print this help text and exit\n";
41 exit(EXIT_FAILURE);
42 }
43
44 void setInterestName(const Name& prefix)
45 {
46 m_interestName = prefix;
47 }
48
49 void
50 setSecondInterestInterval(int interestInterval)
51 {
52 if (interestInterval <= 0)
53 usage();
54 m_secondInterestInterval = time::milliseconds(interestInterval);
55 }
56
57 void
58 setWaitBeforeQuit(int waitTime)
59 {
60 if (waitTime <= 0)
61 usage();
62 m_waitBeforeQuit = time::milliseconds(waitTime);
63 }
64
65 void
66 signalHandler()
67 {
68 m_face.shutdown();
69 m_ioService.stop();
70
71 exit(EXIT_FAILURE);
72 }
73
74 void
75 onData(const Interest& interest, const Data& data)
76 {
77 std::cout << "DATA received for: " << interest.getName() << std::endl;
78 }
79
80 void
81 onTimeout(const Interest& interest)
82 {
83 std::cout << "TIMEOUT received for: " << interest.getName() << std::endl;
84 }
85
86 void
87 onNack(const Interest& interest,
88 const lp::Nack& nack)
89 {
90 std::cout << "NACK received for: " << interest.getName()
91 << " Nonce: " << interest.getNonce()
92 << " Reason: " << nack.getReason()
93 << std::endl;
94 }
95 void
96 sendSecondInterest(boost::asio::deadline_timer* timer)
97 {
98 Interest interest(m_interestName);
99 interest.setInterestLifetime(m_interestLifetime);
100 interest.setNonce(m_nonce2);
101
102 std::cout << "Sending Interest 2: " << interest.getName()
103 << " Nonce: " << interest.getNonce()
104 << std::endl;
105
106 m_face.expressInterest(interest,
107 bind(&TestNackConsumer::onData,
108 this, _1, _2),
109 bind(&TestNackConsumer::onNack,
110 this, _1, _2),
111 bind(&TestNackConsumer::onTimeout,
112 this, _1));
113 }
114
115 void
116 exitProgram(boost::asio::deadline_timer* timer)
117 {
118 m_face.shutdown();
119 m_ioService.stop();
120 }
121
122 void
123 run()
124 {
125 boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
126 signalSet.async_wait(bind(&TestNackConsumer::signalHandler, this));
127
128 boost::asio::deadline_timer sendSecondInterestTimer(m_ioService,
129 boost::posix_time::millisec(m_secondInterestInterval.count()));
130 boost::asio::deadline_timer exitTimer(m_ioService,
131 boost::posix_time::millisec(m_waitBeforeQuit.count()));
132
133 sendSecondInterestTimer.expires_at(sendSecondInterestTimer.expires_at() +
134 boost::posix_time::millisec(m_secondInterestInterval.count()));
135 exitTimer.expires_at(exitTimer.expires_at() +
136 boost::posix_time::millisec(m_waitBeforeQuit.count()));
137
138 try {
139 Interest interest(m_interestName);
140 interest.setInterestLifetime(m_interestLifetime);
141 interest.setNonce(m_nonce1);
142
143 std::cout << "Sending Interest 1: " << interest.getName()
144 << " Nonce: " << interest.getNonce()
145 << std::endl;
146
147 m_face.expressInterest(interest,
148 bind(&TestNackConsumer::onData,
149 this, _1, _2),
150 bind(&TestNackConsumer::onNack,
151 this, _1, _2),
152 bind(&TestNackConsumer::onTimeout,
153 this, _1));
154
155 if (m_secondInterestInterval != time::milliseconds(0))
156 {
157 // Schedule second interest
158 sendSecondInterestTimer.async_wait(bind(&TestNackConsumer::sendSecondInterest,
159 this,
160 &sendSecondInterestTimer));
161 }
162
163 // Schedule exit
164 exitTimer.async_wait(bind(&TestNackConsumer::exitProgram, this, &exitTimer));
165 m_face.processEvents();
166 }
167 catch (const std::exception& exception) {
168 m_ioService.stop();
169 }
170 }
171
172private:
173 boost::asio::io_service m_ioService;
174 std::string m_programName;
175 Face m_face;
176 Name m_interestName;
177 time::milliseconds m_interestLifetime;
178 time::milliseconds m_secondInterestInterval;
179 time::milliseconds m_waitBeforeQuit;
180 uint32_t m_nonce1;
181 uint32_t m_nonce2;
182};
183
184} // namespace ndn
185
186int
187main(int argc, char* argv[])
188{
189 std::srand(std::time(nullptr));
190 int argNumber = 0;
191 ndn::TestNackConsumer testNackConsumer(argv[0]);
192
193 int option;
194 while ((option = getopt(argc, argv, "hp:r:w:")) != -1) {
195 switch (option) {
196 case 'h':
197 testNackConsumer.usage();
198 break;
199 case 'p':
200 testNackConsumer.setInterestName(ndn::Name(optarg));
201 ++argNumber;
202 break;
203 case 'r':
204 testNackConsumer.setSecondInterestInterval(atoi(optarg));
205 break;
206 case 'w':
207 testNackConsumer.setWaitBeforeQuit(atoi(optarg));
208 ++argNumber;
209 break;
210 default:
211 testNackConsumer.usage();
212 break;
213 }
214 }
215
216 argc -= optind;
217 argv += optind;
218
219 if (argc || argNumber < 2)
220 testNackConsumer.usage();
221
222 testNackConsumer.run();
223
224 return 0;
225}