poke: add unit testing
refs #3740 Change-Id: I170068cf69463e92b2019cc27747777d224c0232
This commit is contained in:
1 parent
60f8cc12e2
commit
2f041d20af
6 files changed
+606
-288
No files matched your search
@@ -0,0 +1,212 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of ndn-tools (Named Data Networking Essential Tools).
|
||||
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
|
||||
*
|
||||
* ndn-tools is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tools/peek/ndnpoke/ndnpoke.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
#include <ndn-cxx/util/dummy-client-face.hpp>
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
namespace tests {
|
||||
|
||||
using namespace ndn::tests;
|
||||
|
||||
class NdnPokeFixture : public UnitTestTimeFixture
|
||||
{
|
||||
protected:
|
||||
NdnPokeFixture()
|
||||
: face(io, keyChain, {true, true})
|
||||
{
|
||||
keyChain.createIdentity("/test-id");
|
||||
|
||||
inData << "Hello world!";
|
||||
}
|
||||
|
||||
void
|
||||
initialize(const PokeOptions& opts)
|
||||
{
|
||||
poke = make_unique<NdnPoke>(face, keyChain, inData, opts);
|
||||
}
|
||||
|
||||
static PokeOptions
|
||||
makeDefaultOptions()
|
||||
{
|
||||
PokeOptions opt;
|
||||
opt.prefixName = "/poke/test";
|
||||
return opt;
|
||||
}
|
||||
|
||||
protected:
|
||||
boost::asio::io_service io;
|
||||
ndn::util::DummyClientFace face;
|
||||
KeyChain keyChain;
|
||||
unique_ptr<NdnPoke> poke;
|
||||
std::stringstream inData;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Peek)
|
||||
BOOST_FIXTURE_TEST_SUITE(TestNdnPoke, NdnPokeFixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Basic)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
Interest interest("/poke/test");
|
||||
face.receive(interest);
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(FinalBlockId)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
options.prefixName = "/poke/test/123";
|
||||
options.wantLastAsFinalBlockId = true;
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
Interest interest("/poke/test/123");
|
||||
face.receive(interest);
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test/123");
|
||||
BOOST_REQUIRE(face.sentData.back().getFinalBlock());
|
||||
BOOST_CHECK_EQUAL(*(face.sentData.back().getFinalBlock()), name::Component("123"));
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(FreshnessPeriod)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
options.freshnessPeriod = make_optional<time::milliseconds>(1_s);
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
Interest interest("/poke/test");
|
||||
face.receive(interest);
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 1_s);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DigestSha256)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
options.signingInfo.setSha256Signing();
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
Interest interest("/poke/test");
|
||||
face.receive(interest);
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::DigestSha256);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ForceData)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
options.wantForceData = true;
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ExceedMaxPacketSize)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_NDN_PACKET_SIZE; i++) {
|
||||
inData << "A";
|
||||
}
|
||||
|
||||
auto options = makeDefaultOptions();
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
Interest interest("/poke/test");
|
||||
face.receive(interest);
|
||||
BOOST_CHECK_THROW(face.processEvents(), Face::OversizedPacketError);
|
||||
|
||||
// We can't check wasDataSent() correctly here because it will be set to true, even if put failed
|
||||
// due to the packet being oversized.
|
||||
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // TestNdnPoke
|
||||
BOOST_AUTO_TEST_SUITE_END() // Peek
|
||||
|
||||
} // namespace tests
|
||||
} // namespace peek
|
||||
} // namespace ndn
|
||||
@@ -1,285 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of ndn-tools (Named Data Networking Essential Tools).
|
||||
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
|
||||
*
|
||||
* ndn-tools is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
|
||||
*/
|
||||
|
||||
#include "core/version.hpp"
|
||||
|
||||
#include <ndn-cxx/security/signing-helpers.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
|
||||
class NdnPoke : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
NdnPoke(const char* programName)
|
||||
: m_programName(programName)
|
||||
, m_wantForceData(false)
|
||||
, m_wantDigestSha256(false)
|
||||
, m_wantFinalBlockId(false)
|
||||
, m_freshnessPeriod(-1)
|
||||
, m_timeout(-1)
|
||||
, m_isDataSent(false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
std::cout << "\n Usage:\n " << m_programName << " "
|
||||
"[-f] [-D] [-i identity] [-F] [-x freshness] [-w timeout] ndn:/name\n"
|
||||
" Reads payload from stdin and sends it to local NDN forwarder as a "
|
||||
"single Data packet\n"
|
||||
" [-f] - force, send Data without waiting for Interest\n"
|
||||
" [-D] - use DigestSha256 signing method instead of "
|
||||
"SignatureSha256WithRsa\n"
|
||||
" [-i identity] - set identity to be used for signing\n"
|
||||
" [-F] - set FinalBlockId to the last component of Name\n"
|
||||
" [-x] - set FreshnessPeriod in time::milliseconds\n"
|
||||
" [-w timeout] - set Timeout in time::milliseconds\n"
|
||||
" [-h] - print help and exit\n"
|
||||
" [-V] - print version and exit\n"
|
||||
"\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
setForceData()
|
||||
{
|
||||
m_wantForceData = true;
|
||||
}
|
||||
|
||||
void
|
||||
setUseDigestSha256()
|
||||
{
|
||||
m_wantDigestSha256 = true;
|
||||
}
|
||||
|
||||
void
|
||||
setIdentityName(const char* identityName)
|
||||
{
|
||||
m_identityName = make_shared<Name>(identityName);
|
||||
}
|
||||
|
||||
void
|
||||
setLastAsFinalBlockId()
|
||||
{
|
||||
m_wantFinalBlockId = true;
|
||||
}
|
||||
|
||||
void
|
||||
setFreshnessPeriod(int freshnessPeriod)
|
||||
{
|
||||
if (freshnessPeriod < 0)
|
||||
usage();
|
||||
|
||||
m_freshnessPeriod = time::milliseconds(freshnessPeriod);
|
||||
}
|
||||
|
||||
void
|
||||
setTimeout(int timeout)
|
||||
{
|
||||
if (timeout < 0)
|
||||
usage();
|
||||
|
||||
m_timeout = time::milliseconds(timeout);
|
||||
}
|
||||
|
||||
void
|
||||
setPrefixName(const char* prefixName)
|
||||
{
|
||||
m_prefixName = Name(prefixName);
|
||||
}
|
||||
|
||||
time::milliseconds
|
||||
getDefaultTimeout()
|
||||
{
|
||||
return time::seconds(10);
|
||||
}
|
||||
|
||||
shared_ptr<Data>
|
||||
createDataPacket()
|
||||
{
|
||||
auto dataPacket = make_shared<Data>(m_prefixName);
|
||||
|
||||
std::stringstream payloadStream;
|
||||
payloadStream << std::cin.rdbuf();
|
||||
std::string payload = payloadStream.str();
|
||||
dataPacket->setContent(reinterpret_cast<const uint8_t*>(payload.c_str()), payload.length());
|
||||
|
||||
if (m_freshnessPeriod >= time::milliseconds::zero())
|
||||
dataPacket->setFreshnessPeriod(m_freshnessPeriod);
|
||||
|
||||
if (m_wantFinalBlockId) {
|
||||
if (!m_prefixName.empty())
|
||||
dataPacket->setFinalBlock(m_prefixName.get(-1));
|
||||
else {
|
||||
std::cerr << "Name Provided Has 0 Components" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wantDigestSha256) {
|
||||
m_keyChain.sign(*dataPacket, signingWithSha256());
|
||||
}
|
||||
else {
|
||||
if (m_identityName == nullptr) {
|
||||
m_keyChain.sign(*dataPacket);
|
||||
}
|
||||
else {
|
||||
m_keyChain.sign(*dataPacket, signingByIdentity(*m_identityName));
|
||||
}
|
||||
}
|
||||
|
||||
return dataPacket;
|
||||
}
|
||||
|
||||
void
|
||||
onInterest(const Name& name, const Interest& interest, const shared_ptr<Data>& data)
|
||||
{
|
||||
m_face.put(*data);
|
||||
m_isDataSent = true;
|
||||
m_face.shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
onRegisterFailed(const Name& prefix, const std::string& reason)
|
||||
{
|
||||
std::cerr << "Prefix Registration Failure." << std::endl;
|
||||
std::cerr << "Reason = " << reason << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
try {
|
||||
shared_ptr<Data> dataPacket = createDataPacket();
|
||||
if (m_wantForceData) {
|
||||
m_face.put(*dataPacket);
|
||||
m_isDataSent = true;
|
||||
}
|
||||
else {
|
||||
m_face.setInterestFilter(m_prefixName,
|
||||
bind(&NdnPoke::onInterest, this, _1, _2, dataPacket),
|
||||
RegisterPrefixSuccessCallback(),
|
||||
bind(&NdnPoke::onRegisterFailed, this, _1, _2));
|
||||
}
|
||||
|
||||
if (m_timeout < time::milliseconds::zero())
|
||||
m_face.processEvents(getDefaultTimeout());
|
||||
else
|
||||
m_face.processEvents(m_timeout);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
isDataSent() const
|
||||
{
|
||||
return m_isDataSent;
|
||||
}
|
||||
|
||||
private:
|
||||
KeyChain m_keyChain;
|
||||
std::string m_programName;
|
||||
bool m_wantForceData;
|
||||
bool m_wantDigestSha256;
|
||||
shared_ptr<Name> m_identityName;
|
||||
bool m_wantFinalBlockId;
|
||||
time::milliseconds m_freshnessPeriod;
|
||||
time::milliseconds m_timeout;
|
||||
Name m_prefixName;
|
||||
bool m_isDataSent;
|
||||
Face m_face;
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
NdnPoke program(argv[0]);
|
||||
|
||||
int option;
|
||||
while ((option = getopt(argc, argv, "hfDi:Fx:w:V")) != -1) {
|
||||
switch (option) {
|
||||
case 'h':
|
||||
program.usage();
|
||||
break;
|
||||
case 'f':
|
||||
program.setForceData();
|
||||
break;
|
||||
case 'D':
|
||||
program.setUseDigestSha256();
|
||||
break;
|
||||
case 'i':
|
||||
program.setIdentityName(optarg);
|
||||
break;
|
||||
case 'F':
|
||||
program.setLastAsFinalBlockId();
|
||||
break;
|
||||
case 'x':
|
||||
program.setFreshnessPeriod(atoi(optarg));
|
||||
break;
|
||||
case 'w':
|
||||
program.setTimeout(atoi(optarg));
|
||||
break;
|
||||
case 'V':
|
||||
std::cout << "ndnpoke " << tools::VERSION << std::endl;
|
||||
return 0;
|
||||
default:
|
||||
program.usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!argv[0])
|
||||
program.usage();
|
||||
|
||||
program.setPrefixName(argv[0]);
|
||||
program.run();
|
||||
|
||||
if (program.isDataSent())
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace peek
|
||||
} // namespace ndn
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return ndn::peek::main(argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of ndn-tools (Named Data Networking Essential Tools).
|
||||
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
|
||||
*
|
||||
* ndn-tools is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
|
||||
*/
|
||||
|
||||
#include "ndnpoke.hpp"
|
||||
#include "core/version.hpp"
|
||||
|
||||
#include <ndn-cxx/util/io.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
static void
|
||||
usage(std::ostream& os, const po::options_description& options)
|
||||
{
|
||||
os << "Usage: ndnpoke [options] ndn:/name\n"
|
||||
"\n"
|
||||
"Reads payload from stdin and sends it to the local NDN forwarder as a single Data packet\n"
|
||||
"\n"
|
||||
<< options;
|
||||
}
|
||||
|
||||
static int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
PokeOptions options;
|
||||
bool wantDigestSha256;
|
||||
|
||||
po::options_description visibleOptDesc;
|
||||
visibleOptDesc.add_options()
|
||||
("help,h", "print help and exit")
|
||||
("version,V", "print version and exit")
|
||||
("force,f", po::bool_switch(&options.wantForceData),
|
||||
"for, send Data without waiting for Interest")
|
||||
("digest,D", po::bool_switch(&wantDigestSha256),
|
||||
"use DigestSha256 signing method instead of SignatureSha256WithRsa")
|
||||
("identity,i", po::value<std::string>(),
|
||||
"set identity to be used for signing")
|
||||
("final,F", po::bool_switch(&options.wantLastAsFinalBlockId),
|
||||
"set FinalBlockId to the last component of Name")
|
||||
("freshness,x", po::value<int>(),
|
||||
"set FreshnessPeriod in milliseconds")
|
||||
("timeout,w", po::value<int>(),
|
||||
"set Timeout in milliseconds")
|
||||
;
|
||||
|
||||
po::options_description hiddenOptDesc;
|
||||
hiddenOptDesc.add_options()
|
||||
("name", po::value<std::string>(), "Data name");
|
||||
|
||||
po::options_description optDesc;
|
||||
optDesc.add(visibleOptDesc).add(hiddenOptDesc);
|
||||
|
||||
po::positional_options_description optPos;
|
||||
optPos.add("name", -1);
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::store(po::command_line_parser(argc, argv).options(optDesc).positional(optPos).run(), vm);
|
||||
po::notify(vm);
|
||||
}
|
||||
catch (const po::error& e) {
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
// We store timeout here, instead of PokeOptions, because processEvents is called outside the NdnPoke class
|
||||
time::milliseconds timeout = 10_s;
|
||||
|
||||
if (vm.count("help") > 0) {
|
||||
usage(std::cout, visibleOptDesc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vm.count("version") > 0) {
|
||||
std::cout << "ndnpoke " << tools::VERSION << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vm.count("name") > 0) {
|
||||
options.prefixName = vm["name"].as<std::string>();
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: Data name is missing" << std::endl;
|
||||
usage(std::cerr, visibleOptDesc);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (wantDigestSha256) {
|
||||
options.signingInfo.setSha256Signing();
|
||||
}
|
||||
|
||||
if (vm.count("identity") > 0) {
|
||||
if (wantDigestSha256) {
|
||||
std::cerr << "ERROR: Signing identity cannot be specified when using DigestSha256 signing method" << std::endl;
|
||||
usage(std::cerr, visibleOptDesc);
|
||||
return 2;
|
||||
}
|
||||
options.signingInfo.setSigningIdentity(vm["identity"].as<std::string>());
|
||||
}
|
||||
|
||||
if (vm.count("final") > 0) {
|
||||
if (!options.prefixName.empty()) {
|
||||
options.wantLastAsFinalBlockId = true;
|
||||
}
|
||||
else {
|
||||
std::cerr << "The provided Name must have 1 or more components to be used with FinalBlockId option" << std::endl;
|
||||
usage(std::cerr, visibleOptDesc);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (vm.count("freshness") > 0) {
|
||||
if (vm["freshness"].as<int>() >= 0) {
|
||||
options.freshnessPeriod = time::milliseconds(vm["freshness"].as<int>());
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: FreshnessPeriod must be a non-negative integer" << std::endl;
|
||||
usage(std::cerr, visibleOptDesc);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (vm.count("timeout") > 0) {
|
||||
if (vm["timeout"].as<int>() > 0) {
|
||||
timeout = time::milliseconds(vm["timeout"].as<int>());
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: Timeout must a positive integer" << std::endl;
|
||||
usage(std::cerr, visibleOptDesc);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::io_service io;
|
||||
Face face(io);
|
||||
KeyChain keyChain;
|
||||
scheduler::Scheduler scheduler(io);
|
||||
NdnPoke program(face, keyChain, std::cin, options);
|
||||
try {
|
||||
program.afterFinish.connect([&scheduler, &face] {
|
||||
scheduler.scheduleEvent(2_s, [&face] { face.shutdown(); });
|
||||
});
|
||||
program.start();
|
||||
face.processEvents(timeout);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (program.wasDataSent()) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace peek
|
||||
} // namespace ndn
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
return ndn::peek::main(argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of ndn-tools (Named Data Networking Essential Tools).
|
||||
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
|
||||
*
|
||||
* ndn-tools is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
|
||||
*/
|
||||
|
||||
#include "ndnpoke.hpp"
|
||||
|
||||
#include <ndn-cxx/security/signing-helpers.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
|
||||
NdnPoke::NdnPoke(Face& face, KeyChain& keyChain, std::istream& inStream, const PokeOptions& options)
|
||||
: m_face(face)
|
||||
, m_keyChain(keyChain)
|
||||
, m_inStream(inStream)
|
||||
, m_options(options)
|
||||
, m_wasDataSent(false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NdnPoke::start()
|
||||
{
|
||||
shared_ptr<Data> dataPacket = createDataPacket();
|
||||
if (m_options.wantForceData) {
|
||||
m_face.put(*dataPacket);
|
||||
m_wasDataSent = true;
|
||||
}
|
||||
else {
|
||||
m_face.setInterestFilter(m_options.prefixName,
|
||||
bind(&NdnPoke::onInterest, this, _1, _2, dataPacket),
|
||||
nullptr,
|
||||
bind(&NdnPoke::onRegisterFailed, this, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Data>
|
||||
NdnPoke::createDataPacket()
|
||||
{
|
||||
auto dataPacket = make_shared<Data>(m_options.prefixName);
|
||||
|
||||
std::stringstream payloadStream;
|
||||
payloadStream << m_inStream.rdbuf();
|
||||
std::string payload = payloadStream.str();
|
||||
dataPacket->setContent(reinterpret_cast<const uint8_t*>(payload.c_str()), payload.length());
|
||||
|
||||
if (m_options.freshnessPeriod) {
|
||||
dataPacket->setFreshnessPeriod(*m_options.freshnessPeriod);
|
||||
}
|
||||
|
||||
if (m_options.wantLastAsFinalBlockId) {
|
||||
dataPacket->setFinalBlock(m_options.prefixName.get(-1));
|
||||
}
|
||||
|
||||
m_keyChain.sign(*dataPacket, m_options.signingInfo);
|
||||
|
||||
return dataPacket;
|
||||
}
|
||||
|
||||
void
|
||||
NdnPoke::onInterest(const Name& name, const Interest& interest, const shared_ptr<Data>& data)
|
||||
{
|
||||
try {
|
||||
m_face.put(*data);
|
||||
m_wasDataSent = true;
|
||||
}
|
||||
catch (const Face::OversizedPacketError& e) {
|
||||
std::cerr << "Data exceeded maximum packet size" << std::endl;
|
||||
}
|
||||
afterFinish();
|
||||
}
|
||||
|
||||
void
|
||||
NdnPoke::onRegisterFailed(const Name& prefix, const std::string& reason)
|
||||
{
|
||||
std::cerr << "Prefix Registration Failure. Reason = " << reason << std::endl;
|
||||
}
|
||||
|
||||
} // namespace peek
|
||||
} // namespace ndn
|
||||
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of ndn-tools (Named Data Networking Essential Tools).
|
||||
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
|
||||
*
|
||||
* ndn-tools is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
|
||||
*/
|
||||
|
||||
#ifndef NDN_TOOLS_NDNPOKE_NDNPOKE_HPP
|
||||
#define NDN_TOOLS_NDNPOKE_NDNPOKE_HPP
|
||||
|
||||
#include "core/common.hpp"
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
|
||||
/**
|
||||
* \brief options for NdnPoke
|
||||
*/
|
||||
struct PokeOptions
|
||||
{
|
||||
Name prefixName;
|
||||
bool wantForceData = false;
|
||||
security::SigningInfo signingInfo;
|
||||
bool wantLastAsFinalBlockId = false;
|
||||
optional<time::milliseconds> freshnessPeriod = {};
|
||||
};
|
||||
|
||||
class NdnPoke : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
NdnPoke(Face& face, KeyChain& keyChain, std::istream& inStream, const PokeOptions& options);
|
||||
|
||||
void
|
||||
start();
|
||||
|
||||
bool
|
||||
wasDataSent() const
|
||||
{
|
||||
return m_wasDataSent;
|
||||
}
|
||||
|
||||
public:
|
||||
signal::Signal<NdnPoke> afterFinish;
|
||||
|
||||
private:
|
||||
shared_ptr<Data>
|
||||
createDataPacket();
|
||||
|
||||
void
|
||||
onInterest(const Name& name, const Interest& interest, const shared_ptr<Data>& data);
|
||||
|
||||
void
|
||||
onRegisterFailed(const Name& prefix, const std::string& reason);
|
||||
|
||||
private:
|
||||
Face& m_face;
|
||||
KeyChain& m_keyChain;
|
||||
std::istream& m_inStream;
|
||||
const PokeOptions& m_options;
|
||||
|
||||
bool m_wasDataSent;
|
||||
};
|
||||
|
||||
} // namespace peek
|
||||
} // namespace ndn
|
||||
|
||||
#endif // NDN_TOOLS_NDNPOKE_NDNPOKE_HPP
|
||||
+8
-3
@@ -13,12 +13,17 @@ def build(bld):
|
||||
source='ndnpeek/main.cpp',
|
||||
use='ndnpeek-objects')
|
||||
|
||||
bld.objects(
|
||||
target='ndnpoke-objects',
|
||||
source=bld.path.ant_glob('ndnpoke/*.cpp', excl='ndnpoke/main.cpp'),
|
||||
use='core-objects')
|
||||
|
||||
bld.program(
|
||||
target='../../bin/ndnpoke',
|
||||
source='ndn-poke.cpp',
|
||||
use='core-objects')
|
||||
source='ndnpoke/main.cpp',
|
||||
use='ndnpoke-objects')
|
||||
|
||||
## (for unit tests)
|
||||
|
||||
bld(target='peek-objects',
|
||||
use='ndnpeek-objects')
|
||||
use=['ndnpeek-objects', 'ndnpoke-objects'])
|
||||
Reference in new issue
Block a user