poke: code modernization and cleanup
Change-Id: Ia0d5f0b1bc495636f8fac127bec735cc35af66a7
This commit is contained in:
1 parent
c1eb2fcf4b
commit
e75861eddb
8 files changed
+238
-247
No files matched your search
@@ -63,4 +63,4 @@ Example
|
||||
|
||||
Send Interest for ``/app1/video`` and print the received payload only::
|
||||
|
||||
ndnpeek -p ndn:/app1/video
|
||||
ndnpeek -p /app1/video
|
||||
+37
-32
@@ -1,54 +1,59 @@
|
||||
ndnpoke
|
||||
=======
|
||||
|
||||
Usage
|
||||
-----
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
::
|
||||
|
||||
ndnpoke [-h] [-f] [-D] [-i identity] [-F] [-x freshness] [-w timeout] name
|
||||
**ndnpoke** [-h] [-f] [-F] [-x *freshness*] [-i *identity*\|\ -D] [-w *timeout*] [-V] *name*
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
``ndnpoke`` is a simple producer program that reads payload from stdin and publishes it
|
||||
as a single NDN Data packet. The Data packet is published either as a response to the
|
||||
incoming Interest for the given ``name``, or forcefully pushed to the local NDN
|
||||
forwarder's cache if ``-f`` flag is specified.
|
||||
|
||||
The program terminates with return code 0 if Data is sent and with return code 1 when
|
||||
timeout occurs.
|
||||
:program:`ndnpoke` is a simple producer program that reads a payload from the standard
|
||||
input and publishes it as a single Data packet. The Data packet is either sent as a
|
||||
response to an incoming Interest matching *name*, or immediately pushed to the local
|
||||
NDN forwarder as "unsolicited Data" if the **-f** flag is specified.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
``-h``
|
||||
Print usage and exit.
|
||||
``-h, --help``
|
||||
Print help and exit.
|
||||
|
||||
``-f``
|
||||
If specified, send Data without waiting for Interest.
|
||||
``-f, --force``
|
||||
Send the Data packet without waiting for an incoming Interest.
|
||||
|
||||
``-D``
|
||||
If specified, use ``DigestSha256`` signature instead of default ``SignatureSha256WithRsa``.
|
||||
``-F, --final``
|
||||
Set the ``FinalBlockId`` to the last component of *name*.
|
||||
|
||||
``-i``
|
||||
Use ``identity`` to sign the created Data packet.
|
||||
``-x, --freshness <freshness>``
|
||||
Set ``freshness`` (in milliseconds) as the ``FreshnessPeriod``.
|
||||
|
||||
``-F``
|
||||
Set ``FinalBlockId`` to the last component of specified name.
|
||||
``-i, --identity <identity>``
|
||||
Use ``identity`` to sign the Data packet.
|
||||
|
||||
``-x``
|
||||
Set ``FreshnessPeriod`` in milliseconds.
|
||||
``-D, --digest``
|
||||
Use ``DigestSha256`` signature type instead of the default ``SignatureSha256WithRsa``.
|
||||
|
||||
``-w``
|
||||
Wait at most ``timeout`` milliseconds for the incoming Interest. If no Interest arrives
|
||||
within the ``timeout``, the Data packet will not be published.
|
||||
``-w, --timeout <timeout>``
|
||||
Quit the program after ``timeout`` milliseconds, even if no Interest has been received.
|
||||
|
||||
``-V, --version``
|
||||
Print version and exit.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Exit Status
|
||||
-----------
|
||||
|
||||
Create Data packet with content ``hello`` with the name ``ndn:/app/video`` and wait at
|
||||
most 3 seconds for the incoming Interest for it::
|
||||
0: Success
|
||||
|
||||
echo "Hello" | build/bin/ndnpoke -w 3000 ndn:/app/video
|
||||
1: An unspecified error occurred
|
||||
|
||||
2: Malformed command line
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
Create a Data packet with content ``hello`` and name ``/app/video`` and wait at
|
||||
most 3 seconds for a matching Interest to arrive::
|
||||
|
||||
echo "hello" | ndnpoke -w 3000 /app/video
|
||||
+65
-54
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "tools/peek/ndnpoke/ndnpoke.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "tests/identity-management-fixture.hpp"
|
||||
|
||||
#include <ndn-cxx/util/dummy-client-face.hpp>
|
||||
|
||||
@@ -35,37 +36,33 @@ namespace tests {
|
||||
|
||||
using namespace ndn::tests;
|
||||
|
||||
class NdnPokeFixture : public UnitTestTimeFixture
|
||||
class NdnPokeFixture : public IdentityManagementTimeFixture
|
||||
{
|
||||
protected:
|
||||
NdnPokeFixture()
|
||||
: face(io, keyChain, {true, true})
|
||||
{
|
||||
keyChain.createIdentity("/test-id");
|
||||
|
||||
inData << "Hello world!";
|
||||
m_keyChain.createIdentity("/test-id");
|
||||
}
|
||||
|
||||
void
|
||||
initialize(const PokeOptions& opts)
|
||||
initialize(const PokeOptions& opts = makeDefaultOptions())
|
||||
{
|
||||
poke = make_unique<NdnPoke>(face, keyChain, inData, opts);
|
||||
poke = make_unique<NdnPoke>(face, m_keyChain, payload, opts);
|
||||
}
|
||||
|
||||
static PokeOptions
|
||||
makeDefaultOptions()
|
||||
{
|
||||
PokeOptions opt;
|
||||
opt.prefixName = "/poke/test";
|
||||
opt.name = "/poke/test";
|
||||
return opt;
|
||||
}
|
||||
|
||||
protected:
|
||||
boost::asio::io_service io;
|
||||
ndn::util::DummyClientFace face;
|
||||
KeyChain keyChain;
|
||||
ndn::util::DummyClientFace face{io, m_keyChain, {true, true}};
|
||||
std::stringstream payload{"Hello, world!\n"};
|
||||
unique_ptr<NdnPoke> poke;
|
||||
std::stringstream inData;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Peek)
|
||||
@@ -73,11 +70,9 @@ BOOST_FIXTURE_TEST_SUITE(TestNdnPoke, NdnPokeFixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Basic)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
initialize(options);
|
||||
initialize();
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
// Check for prefix registration
|
||||
@@ -88,11 +83,13 @@ BOOST_AUTO_TEST_CASE(Basic)
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_CHECK(poke->didSendData());
|
||||
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().getContentType(), tlv::ContentType_Blob);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getContent(), "150E48656C6C6F2C20776F726C64210A"_block);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
|
||||
// Check for prefix unregistration
|
||||
@@ -100,45 +97,20 @@ BOOST_AUTO_TEST_CASE(Basic)
|
||||
BOOST_CHECK_EQUAL(face.sentInterests.back().getName().getPrefix(4), "/localhost/nfd/rib/unregister");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
face.receive(*makeInterest("/poke/test/123"));
|
||||
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);
|
||||
options.freshnessPeriod = 1_s;
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
face.receive(*makeInterest("/poke/test"));
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_CHECK(poke->didSendData());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
@@ -146,6 +118,29 @@ BOOST_AUTO_TEST_CASE(FreshnessPeriod)
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(FinalBlockId)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
options.name = "/poke/test/123";
|
||||
options.wantFinalBlockId = true;
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
face.receive(*makeInterest(options.name));
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->didSendData());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), options.name);
|
||||
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(DigestSha256)
|
||||
{
|
||||
auto options = makeDefaultOptions();
|
||||
@@ -153,14 +148,13 @@ BOOST_AUTO_TEST_CASE(DigestSha256)
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
face.receive(*makeInterest("/poke/test"));
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
io.run();
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_CHECK(poke->didSendData());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
@@ -175,10 +169,9 @@ BOOST_AUTO_TEST_CASE(ForceData)
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
BOOST_CHECK(poke->wasDataSent());
|
||||
BOOST_CHECK(poke->didSendData());
|
||||
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
|
||||
BOOST_CHECK(!face.sentData.back().getFinalBlock());
|
||||
@@ -186,24 +179,42 @@ BOOST_AUTO_TEST_CASE(ForceData)
|
||||
BOOST_CHECK_EQUAL(face.sentData.back().getSignature().getType(), tlv::SignatureSha256WithEcdsa);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ExceedMaxPacketSize)
|
||||
BOOST_AUTO_TEST_CASE(Timeout)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_NDN_PACKET_SIZE; i++) {
|
||||
inData << "A";
|
||||
}
|
||||
|
||||
auto options = makeDefaultOptions();
|
||||
options.timeout = 4_s;
|
||||
initialize(options);
|
||||
|
||||
poke->start();
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
// Check for prefix registration
|
||||
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face.sentInterests.front().getName().getPrefix(4), "/localhost/nfd/rib/register");
|
||||
|
||||
this->advanceClocks(io, 1_s, 4);
|
||||
|
||||
BOOST_CHECK(!poke->didSendData());
|
||||
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
|
||||
|
||||
// Check for prefix unregistration
|
||||
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2); // One for registration, one for unregistration
|
||||
BOOST_CHECK_EQUAL(face.sentInterests.back().getName().getPrefix(4), "/localhost/nfd/rib/unregister");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OversizedPacket)
|
||||
{
|
||||
payload << std::string(MAX_NDN_PACKET_SIZE, 'A');
|
||||
initialize();
|
||||
|
||||
poke->start();
|
||||
this->advanceClocks(io, 1_ms, 10);
|
||||
|
||||
face.receive(*makeInterest("/poke/test"));
|
||||
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.
|
||||
// No point in checking didSendData() here. The exception is thrown from processEvents(),
|
||||
// not from put(), so didSendData() is still set to true even though no packets are sent.
|
||||
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# ndnpeek and ndnpoke
|
||||
|
||||
**ndnpeek** and **ndnpoke** are a pair of programs to request and make available for retrieval of a single Data packet.
|
||||
**ndnpeek** and **ndnpoke** are a pair of programs to respectively request and serve a single Data packet.
|
||||
|
||||
* **ndnpeek** is a consumer program that sends one Interest and expects one Data.
|
||||
* **ndnpoke** is a producer program that serves one Data in response to an Interest.
|
||||
|
||||
Usage example:
|
||||
|
||||
1. start NFD on local machine
|
||||
2. execute `echo 'HELLO WORLD' | ndnpoke ndn:/localhost/demo/hello`
|
||||
3. on another console, execute `ndnpeek -p ndn:/localhost/demo/hello`
|
||||
1. start NFD
|
||||
2. execute `echo 'HELLO WORLD' | ndnpoke /localhost/demo/hello`
|
||||
3. in another terminal, execute `ndnpeek -p /localhost/demo/hello`
|
||||
|
||||
For more information, consult manpages of these programs.
|
||||
For more information, consult the manpages of these programs.
|
||||
@@ -39,7 +39,7 @@ namespace po = boost::program_options;
|
||||
static void
|
||||
usage(std::ostream& os, const std::string& program, const po::options_description& options)
|
||||
{
|
||||
os << "Usage: " << program << " [options] ndn:/name\n"
|
||||
os << "Usage: " << program << " [options] /name\n"
|
||||
<< "\n"
|
||||
<< "Fetch one data item matching the specified name and write it to the standard output.\n"
|
||||
<< options;
|
||||
|
||||
+71
-84
@@ -28,47 +28,40 @@
|
||||
#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)
|
||||
usage(std::ostream& os, const std::string& program, 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"
|
||||
os << "Usage: " << program << " [options] /name\n"
|
||||
<< "\n"
|
||||
<< "Reads a payload from the standard input and sends it as a single Data packet.\n"
|
||||
<< options;
|
||||
}
|
||||
|
||||
static int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
std::string progName(argv[0]);
|
||||
PokeOptions options;
|
||||
bool wantDigestSha256;
|
||||
bool wantDigestSha256 = false;
|
||||
|
||||
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")
|
||||
("help,h", "print help and exit")
|
||||
("force,f", po::bool_switch(&options.wantForceData),
|
||||
"send the Data packet without waiting for an incoming Interest")
|
||||
("final,F", po::bool_switch(&options.wantFinalBlockId),
|
||||
"set FinalBlockId to the last component of the Data name")
|
||||
("freshness,x", po::value<int>(), "set FreshnessPeriod (in milliseconds)")
|
||||
("identity,i", po::value<std::string>(), "use the specified identity for signing")
|
||||
("digest,D", po::bool_switch(&wantDigestSha256),
|
||||
"use DigestSha256 signing method instead of SignatureSha256WithRsa")
|
||||
("timeout,w", po::value<int>(), "set timeout (in milliseconds)")
|
||||
("version,V", "print version and exit")
|
||||
;
|
||||
|
||||
po::options_description hiddenOptDesc;
|
||||
@@ -91,11 +84,8 @@ main(int argc, char* argv[])
|
||||
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);
|
||||
usage(std::cout, progName, visibleOptDesc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -104,78 +94,75 @@ main(int argc, char* argv[])
|
||||
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);
|
||||
if (vm.count("name") == 0) {
|
||||
std::cerr << "ERROR: missing name\n\n";
|
||||
usage(std::cerr, progName, visibleOptDesc);
|
||||
return 2;
|
||||
}
|
||||
|
||||
try {
|
||||
options.name = vm["name"].as<std::string>();
|
||||
}
|
||||
catch (const Name::Error& e) {
|
||||
std::cerr << "ERROR: invalid name: " << e.what() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (options.name.empty()) {
|
||||
std::cerr << "ERROR: name cannot have zero components" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (vm.count("freshness") > 0) {
|
||||
if (vm["freshness"].as<int>() < 0) {
|
||||
std::cerr << "ERROR: freshness cannot be negative" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
options.freshnessPeriod = time::milliseconds(vm["freshness"].as<int>());
|
||||
}
|
||||
|
||||
if (vm.count("identity") > 0) {
|
||||
if (wantDigestSha256) {
|
||||
std::cerr << "ERROR: conflicting '--digest' and '--identity' options specified" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
try {
|
||||
options.signingInfo.setSigningIdentity(vm["identity"].as<std::string>());
|
||||
}
|
||||
catch (const Name::Error& e) {
|
||||
std::cerr << "ERROR: invalid identity name: " << e.what() << std::endl;
|
||||
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);
|
||||
if (options.wantForceData) {
|
||||
std::cerr << "ERROR: conflicting '--force' and '--timeout' options specified" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
if (vm["timeout"].as<int>() < 0) {
|
||||
std::cerr << "ERROR: timeout cannot be negative" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
options.timeout = time::milliseconds(vm["timeout"].as<int>());
|
||||
}
|
||||
|
||||
boost::asio::io_service io;
|
||||
Face face(io);
|
||||
KeyChain keyChain;
|
||||
NdnPoke program(face, keyChain, std::cin, options);
|
||||
try {
|
||||
Face face;
|
||||
KeyChain keyChain;
|
||||
NdnPoke program(face, keyChain, std::cin, options);
|
||||
|
||||
program.start();
|
||||
face.processEvents(timeout);
|
||||
face.processEvents();
|
||||
|
||||
return program.didSendData() ? 0 : 1;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (program.wasDataSent()) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,79 +27,66 @@
|
||||
|
||||
#include "ndnpoke.hpp"
|
||||
|
||||
#include <ndn-cxx/security/signing-helpers.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <ndn-cxx/encoding/buffer-stream.hpp>
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
|
||||
NdnPoke::NdnPoke(Face& face, KeyChain& keyChain, std::istream& inStream, const PokeOptions& options)
|
||||
: m_face(face)
|
||||
NdnPoke::NdnPoke(Face& face, KeyChain& keyChain, std::istream& input, const PokeOptions& options)
|
||||
: m_options(options)
|
||||
, m_face(face)
|
||||
, m_keyChain(keyChain)
|
||||
, m_inStream(inStream)
|
||||
, m_options(options)
|
||||
, m_wasDataSent(false)
|
||||
, m_input(input)
|
||||
, m_scheduler(m_face.getIoService())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NdnPoke::start()
|
||||
{
|
||||
shared_ptr<Data> dataPacket = createDataPacket();
|
||||
auto data = createData();
|
||||
|
||||
if (m_options.wantForceData) {
|
||||
m_face.put(*dataPacket);
|
||||
m_wasDataSent = true;
|
||||
}
|
||||
else {
|
||||
m_registeredPrefix = m_face.setInterestFilter(m_options.prefixName,
|
||||
bind(&NdnPoke::onInterest, this, _1, _2, dataPacket),
|
||||
nullptr,
|
||||
bind(&NdnPoke::onRegisterFailed, this, _1, _2));
|
||||
m_face.put(*data);
|
||||
m_didSendData = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_registeredPrefix = m_face.setInterestFilter(m_options.name,
|
||||
[this, data] (auto&&...) {
|
||||
m_timeoutEvent.cancel();
|
||||
m_face.put(*data);
|
||||
m_didSendData = true;
|
||||
m_registeredPrefix.cancel();
|
||||
},
|
||||
[this] (auto&&) {
|
||||
m_timeoutEvent = m_scheduler.schedule(m_options.timeout, [this] {
|
||||
m_registeredPrefix.cancel();
|
||||
});
|
||||
},
|
||||
[] (auto&&, const auto& reason) {
|
||||
std::cerr << "Prefix registration failure (" << reason << ")\n";
|
||||
});
|
||||
}
|
||||
|
||||
shared_ptr<Data>
|
||||
NdnPoke::createDataPacket()
|
||||
NdnPoke::createData() const
|
||||
{
|
||||
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());
|
||||
|
||||
auto data = make_shared<Data>(m_options.name);
|
||||
if (m_options.freshnessPeriod) {
|
||||
dataPacket->setFreshnessPeriod(*m_options.freshnessPeriod);
|
||||
data->setFreshnessPeriod(*m_options.freshnessPeriod);
|
||||
}
|
||||
if (m_options.wantFinalBlockId) {
|
||||
data->setFinalBlock(m_options.name.at(-1));
|
||||
}
|
||||
|
||||
if (m_options.wantLastAsFinalBlockId) {
|
||||
dataPacket->setFinalBlock(m_options.prefixName.get(-1));
|
||||
}
|
||||
OBufferStream os;
|
||||
os << m_input.rdbuf();
|
||||
data->setContent(os.buf());
|
||||
|
||||
m_keyChain.sign(*dataPacket, m_options.signingInfo);
|
||||
m_keyChain.sign(*data, 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;
|
||||
}
|
||||
|
||||
m_registeredPrefix.cancel();
|
||||
}
|
||||
|
||||
void
|
||||
NdnPoke::onRegisterFailed(const Name& prefix, const std::string& reason)
|
||||
{
|
||||
std::cerr << "Prefix Registration Failure. Reason = " << reason << std::endl;
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace peek
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include "core/common.hpp"
|
||||
|
||||
#include <ndn-cxx/util/scheduler.hpp>
|
||||
|
||||
namespace ndn {
|
||||
namespace peek {
|
||||
|
||||
@@ -38,45 +40,44 @@ namespace peek {
|
||||
*/
|
||||
struct PokeOptions
|
||||
{
|
||||
Name prefixName;
|
||||
bool wantForceData = false;
|
||||
// Data construction options
|
||||
Name name;
|
||||
optional<time::milliseconds> freshnessPeriod;
|
||||
bool wantFinalBlockId = false;
|
||||
security::SigningInfo signingInfo;
|
||||
bool wantLastAsFinalBlockId = false;
|
||||
optional<time::milliseconds> freshnessPeriod = {};
|
||||
|
||||
// program behavior options
|
||||
bool wantForceData = false;
|
||||
time::milliseconds timeout = 10_s;
|
||||
};
|
||||
|
||||
class NdnPoke : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
NdnPoke(Face& face, KeyChain& keyChain, std::istream& inStream, const PokeOptions& options);
|
||||
NdnPoke(Face& face, KeyChain& keyChain, std::istream& input, const PokeOptions& options);
|
||||
|
||||
void
|
||||
start();
|
||||
|
||||
bool
|
||||
wasDataSent() const
|
||||
didSendData() const
|
||||
{
|
||||
return m_wasDataSent;
|
||||
return m_didSendData;
|
||||
}
|
||||
|
||||
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);
|
||||
createData() const;
|
||||
|
||||
private:
|
||||
const PokeOptions m_options;
|
||||
Face& m_face;
|
||||
KeyChain& m_keyChain;
|
||||
std::istream& m_inStream;
|
||||
const PokeOptions& m_options;
|
||||
|
||||
RegisteredPrefixHandle m_registeredPrefix;
|
||||
bool m_wasDataSent;
|
||||
std::istream& m_input;
|
||||
Scheduler m_scheduler;
|
||||
ScopedRegisteredPrefixHandle m_registeredPrefix;
|
||||
scheduler::ScopedEventId m_timeoutEvent;
|
||||
bool m_didSendData = false;
|
||||
};
|
||||
|
||||
} // namespace peek
|
||||
|
||||
Reference in new issue
Block a user