| /* -*- 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 { |
| namespace ping { |
| |
| class NdnPingServer : boost::noncopyable |
| { |
| public: |
| explicit |
| NdnPingServer(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) |
| usage(); |
| |
| 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(&NdnPingServer::onInterest, |
| this, _1, _2), |
| bind(&NdnPingServer::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; |
| |
| NdnPingServer program(argv[0]); |
| while ((res = getopt(argc, argv, "hdtp:x:")) != -1) |
| { |
| switch (res) { |
| case 'h': |
| program.usage(); |
| break; |
| case 'p': |
| program.setMaximumPings(atoi(optarg)); |
| break; |
| case 'x': |
| program.setFreshnessPeriod(atoi(optarg)); |
| break; |
| case 't': |
| program.setPrintTimestamp(); |
| break; |
| default: |
| program.usage(); |
| break; |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| |
| if (argv[0] == 0) |
| program.usage(); |
| |
| program.setPrefix(argv[0]); |
| program.run(); |
| |
| std::cout << std::endl; |
| |
| if (program.hasError()) |
| return 1; |
| else |
| return 0; |
| } |
| |
| } // namespace ping |
| } // namespace ndn |
| |
| int |
| main(int argc, char** argv) |
| { |
| return ndn::ping::main(argc, argv); |
| } |