| /** |
| * This program is used by test_nack interation test. |
| * The program implements a simple consumer that sends one or |
| * two interests and prints the network response (timeout, data or nack). |
| * ndnpeek is not sufficient since it does not allow verifying |
| * the nonces as required by the test. |
| */ |
| |
| #include <boost/asio.hpp> |
| #include <ndn-cxx/face.hpp> |
| |
| namespace ndn { |
| |
| class TestNackConsumer : boost::noncopyable |
| { |
| public: |
| explicit |
| TestNackConsumer(const char* programName) |
| : m_programName(programName) |
| , m_face(m_ioService) |
| , m_interestLifetime(time::milliseconds(4000)) |
| , m_secondInterestInterval(time::milliseconds(0)) |
| { |
| m_nonce1 = static_cast<uint32_t>(std::rand()); |
| m_nonce2 = static_cast<uint32_t>(std::rand()); |
| } |
| |
| void |
| usage() const |
| { |
| std::cout << "Usage:\n" |
| << " " << m_programName |
| << " -p <name> -w <wait_before_quit> [-r second_Interest_interval] \n" |
| << "\n" |
| << " -p <name> Interest prefix\n" |
| << " -w <wait_before_quit> - wait time(ms) before exit\n" |
| << "\n" |
| << "Options:\n" |
| << " [-r second_Interest_interval] - set the time (ms) between first and second Interests\n" |
| << " [-h] - print this help text and exit\n"; |
| exit(EXIT_FAILURE); |
| } |
| |
| void setInterestName(const Name& prefix) |
| { |
| m_interestName = prefix; |
| } |
| |
| void |
| setSecondInterestInterval(int interestInterval) |
| { |
| if (interestInterval <= 0) |
| usage(); |
| m_secondInterestInterval = time::milliseconds(interestInterval); |
| } |
| |
| void |
| setWaitBeforeQuit(int waitTime) |
| { |
| if (waitTime <= 0) |
| usage(); |
| m_waitBeforeQuit = time::milliseconds(waitTime); |
| } |
| |
| void |
| signalHandler() |
| { |
| m_face.shutdown(); |
| m_ioService.stop(); |
| |
| exit(EXIT_FAILURE); |
| } |
| |
| void |
| onData(const Interest& interest, const Data& data) |
| { |
| std::cout << "DATA received for: " << interest.getName() << std::endl; |
| } |
| |
| void |
| onTimeout(const Interest& interest) |
| { |
| std::cout << "TIMEOUT received for: " << interest.getName() << std::endl; |
| } |
| |
| void |
| onNack(const Interest& interest, |
| const lp::Nack& nack) |
| { |
| std::cout << "NACK received for: " << interest.getName() |
| << " Nonce: " << interest.getNonce() |
| << " Reason: " << nack.getReason() |
| << std::endl; |
| } |
| void |
| sendSecondInterest(boost::asio::deadline_timer* timer) |
| { |
| Interest interest(m_interestName); |
| interest.setInterestLifetime(m_interestLifetime); |
| interest.setNonce(m_nonce2); |
| |
| std::cout << "Sending Interest 2: " << interest.getName() |
| << " Nonce: " << interest.getNonce() |
| << std::endl; |
| |
| m_face.expressInterest(interest, |
| bind(&TestNackConsumer::onData, |
| this, _1, _2), |
| bind(&TestNackConsumer::onNack, |
| this, _1, _2), |
| bind(&TestNackConsumer::onTimeout, |
| this, _1)); |
| } |
| |
| void |
| exitProgram(boost::asio::deadline_timer* timer) |
| { |
| m_face.shutdown(); |
| m_ioService.stop(); |
| } |
| |
| void |
| run() |
| { |
| boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM); |
| signalSet.async_wait(bind(&TestNackConsumer::signalHandler, this)); |
| |
| boost::asio::deadline_timer sendSecondInterestTimer(m_ioService, |
| boost::posix_time::millisec(m_secondInterestInterval.count())); |
| boost::asio::deadline_timer exitTimer(m_ioService, |
| boost::posix_time::millisec(m_waitBeforeQuit.count())); |
| |
| sendSecondInterestTimer.expires_at(sendSecondInterestTimer.expires_at() + |
| boost::posix_time::millisec(m_secondInterestInterval.count())); |
| exitTimer.expires_at(exitTimer.expires_at() + |
| boost::posix_time::millisec(m_waitBeforeQuit.count())); |
| |
| try { |
| Interest interest(m_interestName); |
| interest.setInterestLifetime(m_interestLifetime); |
| interest.setNonce(m_nonce1); |
| |
| std::cout << "Sending Interest 1: " << interest.getName() |
| << " Nonce: " << interest.getNonce() |
| << std::endl; |
| |
| m_face.expressInterest(interest, |
| bind(&TestNackConsumer::onData, |
| this, _1, _2), |
| bind(&TestNackConsumer::onNack, |
| this, _1, _2), |
| bind(&TestNackConsumer::onTimeout, |
| this, _1)); |
| |
| if (m_secondInterestInterval != time::milliseconds(0)) |
| { |
| // Schedule second interest |
| sendSecondInterestTimer.async_wait(bind(&TestNackConsumer::sendSecondInterest, |
| this, |
| &sendSecondInterestTimer)); |
| } |
| |
| // Schedule exit |
| exitTimer.async_wait(bind(&TestNackConsumer::exitProgram, this, &exitTimer)); |
| m_face.processEvents(); |
| } |
| catch (const std::exception& exception) { |
| m_ioService.stop(); |
| } |
| } |
| |
| private: |
| boost::asio::io_service m_ioService; |
| std::string m_programName; |
| Face m_face; |
| Name m_interestName; |
| time::milliseconds m_interestLifetime; |
| time::milliseconds m_secondInterestInterval; |
| time::milliseconds m_waitBeforeQuit; |
| uint32_t m_nonce1; |
| uint32_t m_nonce2; |
| }; |
| |
| } // namespace ndn |
| |
| int |
| main(int argc, char* argv[]) |
| { |
| std::srand(std::time(nullptr)); |
| int argNumber = 0; |
| ndn::TestNackConsumer testNackConsumer(argv[0]); |
| |
| int option; |
| while ((option = getopt(argc, argv, "hp:r:w:")) != -1) { |
| switch (option) { |
| case 'h': |
| testNackConsumer.usage(); |
| break; |
| case 'p': |
| testNackConsumer.setInterestName(ndn::Name(optarg)); |
| ++argNumber; |
| break; |
| case 'r': |
| testNackConsumer.setSecondInterestInterval(atoi(optarg)); |
| break; |
| case 'w': |
| testNackConsumer.setWaitBeforeQuit(atoi(optarg)); |
| ++argNumber; |
| break; |
| default: |
| testNackConsumer.usage(); |
| break; |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| |
| if (argc || argNumber < 2) |
| testNackConsumer.usage(); |
| |
| testNackConsumer.run(); |
| |
| return 0; |
| } |