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