blob: fb6cb969c80e5364929b2f90a9edb19a129f3fab [file] [log] [blame]
/**
* 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;
}