blob: 1dcee214fc1237e578659f826d350b9db66c77c9 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2017, Regents of the University of California,
*
* This file is part of NFD Control Center. See AUTHORS.md for complete list of NFD
* authors and contributors.
*
* NFD Control Center 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.
*
* NFD Control Center 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 NFD
* Control Center, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>
#include "tray-menu.hpp"
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/mgmt/nfd/fib-entry.hpp>
#include <ndn-cxx/mgmt/nfd/controller.hpp>
#include <ndn-cxx/mgmt/nfd/status-dataset.hpp>
#include <boost/thread.hpp>
namespace ndn {
class Ncc
{
public:
Ncc()
: m_isActive(true)
, m_localhopFibEntry(Name("/localhop/nfd"))
, m_face(nullptr, m_keyChain)
, m_controller(m_face, m_keyChain)
, m_scheduler(m_face.getIoService())
, m_tray(m_engine.rootContext(), m_face, m_keyChain)
{
QQmlContext* context = m_engine.rootContext();
context->setContextProperty("trayModel", &m_tray);
m_engine.load((QUrl("qrc:/main.qml")));
m_nfdThread = boost::thread(&Ncc::nfdConnectionLoop, this);
}
void
nfdConnectionLoop()
{
try {
#ifdef BOOST_THREAD_USES_CHRONO
time::seconds retryTimeout = time::seconds(5);
#else
boost::posix_time::time_duration retryTimeout = boost::posix_time::seconds(1);
#endif
while (m_isActive) {
try {
while (m_isActive) {
requestNfdStatus();
m_face.processEvents(time::milliseconds::zero(), true);
}
}
catch (const std::exception& e) {
emit m_tray.nfdActivityUpdate(false);
m_face.shutdown();
#ifdef BOOST_THREAD_USES_CHRONO
boost::this_thread::sleep_for(retryTimeout);
#else
boost::this_thread::sleep(retryTimeout);
#endif
}
}
}
catch (const boost::thread_interrupted&) {
// done
}
}
void
onStatusRetrieved(const nfd::ForwarderStatus& status)
{
emit m_tray.nfdActivityUpdate(true);
m_controller.fetch<ndn::nfd::FibDataset>(bind(&Ncc::onFibStatusRetrieved, this, _1),
bind(&Ncc::onStatusTimeout, this));
m_scheduler.scheduleEvent(time::seconds(6), bind(&Ncc::requestNfdStatus, this));
}
void
onFibStatusRetrieved(const std::vector<nfd::FibEntry>& status)
{
bool isConnectedToHub = false;
for (auto const& fibEntry : status) {
if (fibEntry.getPrefix() == m_localhopFibEntry) {
isConnectedToHub = true;
}
}
emit m_tray.connectivityUpdate(isConnectedToHub);
}
void
onStatusTimeout()
{
emit m_tray.nfdActivityUpdate(false);
std::cerr << "Should not really happen, most likely a serious problem" << std::endl;
m_scheduler.scheduleEvent(time::seconds(6), bind(&Ncc::requestNfdStatus, this));
}
void
stop()
{
m_isActive = false;
m_face.shutdown();
m_scheduler.cancelAllEvents();
m_nfdThread.interrupt();
m_nfdThread.join();
}
private:
void
requestNfdStatus()
{
m_controller.fetch<ndn::nfd::ForwarderGeneralStatusDataset>(bind(&Ncc::onStatusRetrieved, this, _1),
bind(&Ncc::onStatusTimeout, this));
}
private:
volatile bool m_isActive;
boost::thread m_nfdThread;
const Name m_localhopFibEntry;
KeyChain m_keyChain;
Face m_face;
nfd::Controller m_controller;
Scheduler m_scheduler;
QQmlApplicationEngine m_engine;
ncc::TrayMenu m_tray;
};
} // namespace ndn
Q_DECLARE_METATYPE(ndn::shared_ptr<const ndn::Data>)
Q_DECLARE_METATYPE(ndn::nfd::ForwarderStatus)
Q_DECLARE_METATYPE(std::vector<ndn::nfd::FibEntry>)
Q_DECLARE_METATYPE(std::vector<ndn::nfd::RibEntry>)
Q_DECLARE_METATYPE(std::vector<ndn::nfd::FaceStatus>)
Q_DECLARE_METATYPE(std::vector<ndn::nfd::ChannelStatus>)
Q_DECLARE_METATYPE(std::vector<ndn::nfd::StrategyChoice>)
int
main(int argc, char *argv[])
{
ndn::KeyChain keyChain;
ndn::Data data("/to/request/or/check/keychain/permissions");
keyChain.sign(data);
qRegisterMetaType<ndn::shared_ptr<const ndn::Data>>();
qRegisterMetaType<ndn::nfd::ForwarderStatus>();
qRegisterMetaType<std::vector<ndn::nfd::FibEntry>>();
qRegisterMetaType<std::vector<ndn::nfd::RibEntry>>();
qRegisterMetaType<std::vector<ndn::nfd::FaceStatus>>();
qRegisterMetaType<std::vector<ndn::nfd::ChannelStatus>>();
qRegisterMetaType<std::vector<ndn::nfd::StrategyChoice>>();
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication app(argc, argv);
ndn::Ncc controlCenterGui;
QApplication::setQuitOnLastWindowClosed(false);
int retval = app.exec();
controlCenterGui.stop();
return retval;
}