| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /* |
| * Copyright (c) 2014-2023, Regents of the University of California. |
| * |
| * This file is part of NDN repo-ng (Next generation of NDN repository). |
| * See AUTHORS.md for complete list of repo-ng authors and contributors. |
| * |
| * repo-ng 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. |
| * |
| * repo-ng 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 |
| * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /** |
| * @file This file demonstrates how to generate data to be stored in a repo using |
| * the repo watch protocol and repo insertion protocol. |
| * |
| * The details of the protocols can be found here: |
| * <https://redmine.named-data.net/projects/repo-ng/wiki/Watched_Prefix_Insertion_Protocol> |
| * <https://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol> |
| * |
| * This file is used for debugging purpose. There are two modes for users to assign |
| * names for the data. |
| * 1)read the data name from a specific file |
| * 2)input a prefix and a random version number will be added automatically |
| * Users need to run nfd and repo-ng and set up specific repo protocols mentioned |
| * above before running this program. |
| * The description of command parameter can be found in the function usage(). |
| */ |
| |
| #include <boost/asio/io_context.hpp> |
| #include <boost/lexical_cast.hpp> |
| |
| #include <ndn-cxx/data.hpp> |
| #include <ndn-cxx/face.hpp> |
| #include <ndn-cxx/name.hpp> |
| #include <ndn-cxx/util/random.hpp> |
| #include <ndn-cxx/util/scheduler.hpp> |
| #include <ndn-cxx/util/time.hpp> |
| |
| #include <fstream> |
| #include <iostream> |
| #include <random> |
| #include <string> |
| |
| namespace repo::examples { |
| |
| enum Mode { |
| AUTO, |
| READFILE |
| }; |
| |
| class Publisher |
| { |
| public: |
| class Error : public std::runtime_error |
| { |
| public: |
| using std::runtime_error::runtime_error; |
| }; |
| |
| public: |
| void |
| run(); |
| |
| void |
| autoGenerate(); |
| |
| void |
| generateFromFile(); |
| |
| static std::shared_ptr<ndn::Data> |
| createData(const ndn::Name& name); |
| |
| public: |
| std::ifstream insertStream; |
| Mode mode{AUTO}; |
| ndn::Name dataPrefix{"/example/data"}; |
| ndn::time::milliseconds timeInterval{2000}; |
| ndn::time::milliseconds duration{0}; |
| |
| private: |
| ndn::Face m_face; |
| ndn::Scheduler m_scheduler{m_face.getIoContext()}; |
| std::uniform_int_distribution<> m_randomDist{200, 1000}; |
| }; |
| |
| void |
| Publisher::run() |
| { |
| if (mode == AUTO) { |
| m_scheduler.schedule(timeInterval, [this] { autoGenerate(); }); |
| } |
| else { |
| m_scheduler.schedule(timeInterval, [this] { generateFromFile(); }); |
| } |
| m_face.processEvents(duration); |
| } |
| |
| void |
| Publisher::autoGenerate() |
| { |
| ndn::Name name = dataPrefix; |
| name.appendNumber(m_randomDist(ndn::random::getRandomNumberEngine())); |
| auto data = createData(name); |
| m_face.put(*data); |
| |
| m_scheduler.schedule(timeInterval, [this] { autoGenerate(); }); |
| } |
| |
| void |
| Publisher::generateFromFile() |
| { |
| if (insertStream.eof()) { |
| m_face.getIoContext().stop(); |
| return; |
| } |
| |
| std::string name; |
| getline(insertStream, name); |
| auto data = createData(name); |
| m_face.put(*data); |
| |
| m_scheduler.schedule(timeInterval, [this] { generateFromFile(); }); |
| } |
| |
| std::shared_ptr<ndn::Data> |
| Publisher::createData(const ndn::Name& name) |
| { |
| static ndn::KeyChain keyChain; |
| static const std::vector<uint8_t> content(1500, '-'); |
| |
| auto data = std::make_shared<ndn::Data>(name); |
| data->setContent(content); |
| keyChain.sign(*data); |
| return data; |
| } |
| |
| static void |
| usage() |
| { |
| std::cerr |
| << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n" |
| << " -d: specify the data prefix publisher generate\n" |
| << " -f: specify filename that publish would read from\n" |
| << " -s: specify the time duration of generate data\n" |
| << " -t: specify the time interval between two data generated\n" |
| << std::endl; |
| exit(1); |
| } |
| |
| static int |
| main(int argc, char* argv[]) |
| { |
| Publisher generator; |
| bool isAuto = false; |
| bool isRead = false; |
| int opt; |
| while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) { |
| switch (opt) { |
| case 'd': |
| { |
| generator.dataPrefix = ndn::Name(std::string(optarg)); |
| generator.mode = AUTO; |
| isAuto = true; |
| } |
| break; |
| case 'f': |
| { |
| isRead = true; |
| generator.mode = READFILE; |
| std::string str = std::string(optarg); |
| generator.insertStream.open(str.c_str()); |
| if (!generator.insertStream.is_open()) { |
| std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl; |
| return 1; |
| } |
| } |
| break; |
| case 's': |
| try { |
| generator.duration = ndn::time::milliseconds(boost::lexical_cast<uint64_t>(optarg)); |
| } |
| catch (const boost::bad_lexical_cast&) { |
| std::cerr << "-s option should be an integer" << std::endl; |
| return 1; |
| } |
| break; |
| case 't': |
| try { |
| generator.timeInterval = ndn::time::milliseconds(boost::lexical_cast<uint64_t>(optarg)); |
| } |
| catch (const boost::bad_lexical_cast&) { |
| std::cerr << "-t option should be an integer" << std::endl; |
| return 1; |
| } |
| break; |
| default: |
| usage(); |
| break; |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| |
| if (argc != 0) |
| usage(); |
| |
| if (isAuto && isRead) |
| usage(); |
| |
| generator.run(); |
| return 0; |
| } |
| |
| } // namespace repo::examples |
| |
| int |
| main(int argc, char* argv[]) |
| { |
| try { |
| return repo::examples::main(argc, argv); |
| } |
| catch (const std::exception& e) { |
| std::cerr << "ERROR: " << e.what() << std::endl; |
| return 2; |
| } |
| } |