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