ping: import code from ndn-tlv-ping repository
This is an exact copy of code from
ndn-tlv-ping:commit:d3675f528af468d59b2c505057acd21b56210c5c
refs #2525
Change-Id: I4cd93087cf28737fa109183e83aa3bcf60c0f6ff
diff --git a/tools/ping/ndn-ping-server.cpp b/tools/ping/ndn-ping-server.cpp
new file mode 100644
index 0000000..dfe6538
--- /dev/null
+++ b/tools/ping/ndn-ping-server.cpp
@@ -0,0 +1,226 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2014 Arizona Board of Regents
+ *
+ * This file is part of ndn-tlv-ping (Ping Application for Named Data Networking).
+ *
+ * ndn-tlv-ping is a 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-tlv-ping 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-tlv-ping, e.g., in LICENSE file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ */
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/name.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+#include <boost/asio.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace ndn {
+
+class NdnTlvPingServer : boost::noncopyable
+{
+public:
+
+ explicit
+ NdnTlvPingServer(char* programName)
+ : m_programName(programName)
+ , m_hasError(false)
+ , m_isPrintTimestampSet(false)
+ , m_freshnessPeriod(getMinimumFreshnessPeriod())
+ , m_maximumPings(-1)
+ , m_totalPings(0)
+ , m_face(m_ioService)
+ {
+ }
+
+ void
+ usage()
+ {
+ std::cout << "\n Usage:\n " << m_programName << " ndn:/name/prefix [options]\n"
+ " Starts a NDN ping server that responds to Interests with name"
+ " ndn:/name/prefix/ping/number.\n"
+ " [-x freshness] - set FreshnessSeconds\n"
+ " [-p] - specify number of pings to be satisfied (>=1)\n"
+ " [-t] - print timestamp\n"
+ " [-h] - print this message and exit\n\n";
+ exit(1);
+ }
+
+ time::milliseconds
+ getMinimumFreshnessPeriod()
+ {
+ return time::milliseconds(1000);
+ }
+
+ void
+ setFreshnessPeriod(int freshnessPeriod)
+ {
+ if (freshnessPeriod <= 0)
+
+ m_freshnessPeriod = time::milliseconds(freshnessPeriod);
+ }
+
+ void
+ setMaximumPings(int maximumPings)
+ {
+ if (maximumPings <= 0)
+ usage();
+ m_maximumPings = maximumPings;
+ }
+
+ void
+ setPrefix(char* prefix)
+ {
+ m_prefix = prefix;
+ }
+
+ void
+ setPrintTimestamp()
+ {
+ m_isPrintTimestampSet = true;
+ }
+
+ bool
+ hasError() const
+ {
+ return m_hasError;
+ }
+
+ void
+ onInterest(const Name& name, const Interest& interest)
+ {
+ Name interestName = interest.getName();
+ if (m_isPrintTimestampSet)
+ std::cout << time::toIsoString(time::system_clock::now()) << " - ";
+ std::cout << "Interest Received - Ping Reference = "
+ << interestName.at(-1).toUri() << std::endl;
+ char responseContent[] = "NDN TLV Ping Response";
+ shared_ptr<Data> data = make_shared<Data>(interestName);
+ data->setFreshnessPeriod(m_freshnessPeriod);
+ data->setContent(reinterpret_cast<const uint8_t*>(responseContent),
+ sizeof(responseContent));
+ m_keyChain.sign(*data);
+ m_face.put(*data);
+ ++m_totalPings;
+ if (m_maximumPings > 0 && m_maximumPings == m_totalPings) {
+ std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
+ std::cout << "Shutting Down Ping Server (" << m_name << ").\n" << std::endl;
+ m_face.shutdown();
+ m_ioService.stop();
+ }
+ }
+
+ void
+ onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
+ {
+ std::cerr << "ERROR: Failed to register prefix in local hub's daemon" << std::endl;
+ std::cerr << "REASON: " << reason << std::endl;
+ m_hasError = true;
+ m_face.shutdown();
+ m_ioService.stop();
+ }
+
+ void
+ signalHandler()
+ {
+ std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
+ std::cout << "Shutting Down Ping Server (" << m_name.toUri() << ").\n" << std::endl;
+ m_face.shutdown();
+ exit(1);
+ }
+
+ void
+ run()
+ {
+ std::cout << "\n=== Ping Server " << m_prefix <<" ===\n" << std::endl;
+
+ boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
+ signalSet.async_wait(bind([this]() { signalHandler(); }));
+ m_name = m_prefix;
+ m_name.append("ping");
+ m_face.setInterestFilter(m_name,
+ bind(&NdnTlvPingServer::onInterest,
+ this, _1, _2),
+ bind(&NdnTlvPingServer::onRegisterFailed,
+ this, _1,_2));
+ try {
+ m_face.processEvents();
+ }
+ catch (std::exception& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ m_hasError = true;
+ m_ioService.stop();
+ }
+ }
+
+private:
+ char* m_programName;
+ bool m_hasError;
+ bool m_isPrintTimestampSet;
+ time::milliseconds m_freshnessPeriod;
+ int m_maximumPings;
+ int m_totalPings;
+
+ char* m_prefix;
+ Name m_name;
+
+ boost::asio::io_service m_ioService;
+ KeyChain m_keyChain;
+ Face m_face;
+};
+
+}
+
+int
+main(int argc, char* argv[])
+{
+ int res;
+
+ ndn::NdnTlvPingServer ndnTlvPingServer(argv[0]);
+ while ((res = getopt(argc, argv, "hdtp:x:")) != -1)
+ {
+ switch (res) {
+ case 'h':
+ ndnTlvPingServer.usage();
+ break;
+ case 'p':
+ ndnTlvPingServer.setMaximumPings(atoi(optarg));
+ break;
+ case 'x':
+ ndnTlvPingServer.setFreshnessPeriod(atoi(optarg));
+ break;
+ case 't':
+ ndnTlvPingServer.setPrintTimestamp();
+ break;
+ default:
+ ndnTlvPingServer.usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argv[0] == 0)
+ ndnTlvPingServer.usage();
+
+ ndnTlvPingServer.setPrefix(argv[0]);
+ ndnTlvPingServer.run();
+
+ std::cout << std::endl;
+
+ if (ndnTlvPingServer.hasError())
+ return 1;
+ else
+ return 0;
+}