[ndnSIM] face: Emulation mode of ndn::Face
Change-Id: Ib345978575104afa436296d2f5a824a39e3a9780
diff --git a/src/detail/face-impl.hpp b/src/detail/face-impl.hpp
index 86945ba..51aff16 100644
--- a/src/detail/face-impl.hpp
+++ b/src/detail/face-impl.hpp
@@ -70,7 +70,7 @@
, m_processEventsTimeoutEvent(m_scheduler)
{
auto postOnEmptyPitOrNoRegisteredPrefixes = [this] {
- this->m_face.getIoService().post([this] { this->onEmptyPitOrNoRegisteredPrefixes(); });
+ m_scheduler.scheduleEvent(time::seconds(0), bind(&Impl::onEmptyPitOrNoRegisteredPrefixes, this));
// without this extra "post", transport can get paused (-async_read) and then resumed
// (+async_read) from within onInterest/onData callback. After onInterest/onData
// finishes, there is another +async_read with the same memory block. A few of such
@@ -371,7 +371,7 @@
ensureConnected(bool wantResume)
{
if (!m_face.m_transport->isConnected())
- m_face.m_transport->connect(m_face.m_ioService,
+ m_face.m_transport->connect(m_face.getIoService(),
[=] (const Block& wire) { m_face.onReceiveElement(wire); });
if (wantResume && !m_face.m_transport->isReceiving()) {
@@ -384,9 +384,6 @@
{
if (m_pendingInterestTable.empty() && m_registeredPrefixTable.empty()) {
m_face.m_transport->pause();
- if (!m_ioServiceWork) {
- m_processEventsTimeoutEvent.cancel();
- }
}
}
@@ -423,8 +420,6 @@
InterestFilterTable m_interestFilterTable;
RegisteredPrefixTable m_registeredPrefixTable;
- unique_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
-
friend class Face;
};
diff --git a/src/face.cpp b/src/face.cpp
index fdb6b29..57b22fa 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -28,15 +28,21 @@
#include "util/random.hpp"
#include "util/time.hpp"
+#include "ns3/node-list.h"
+#include "ns3/ndnSIM/helper/ndn-stack-helper.hpp"
+#include "ns3/ndnSIM/NFD/daemon/face/generic-link-service.hpp"
+#include "ns3/ndnSIM/NFD/daemon/face/internal-transport.hpp"
+
// NDN_LOG_INIT(ndn.Face) is declared in face-impl.hpp
-// A callback scheduled through io.post and io.dispatch may be invoked after the face is destructed.
-// To prevent this situation, use these macros to capture Face::m_impl as weak_ptr and skip callback
-// execution if the face has been destructed.
+// A callback scheduled through io.post and io.dispatch may be invoked after the face
+// is destructed. To prevent this situation, these macros captures Face::m_impl as weak_ptr,
+// and skips callback execution if the face has been destructed.
+
#define IO_CAPTURE_WEAK_IMPL(OP) \
{ \
weak_ptr<Impl> implWeak(m_impl); \
- m_ioService.OP([=] { \
+ m_impl->m_scheduler.scheduleEvent(time::seconds(0), [=] { \
auto impl = implWeak.lock(); \
if (impl != nullptr) {
#define IO_CAPTURE_WEAK_IMPL_END \
@@ -57,50 +63,31 @@
}
Face::Face(shared_ptr<Transport> transport)
- : m_internalIoService(make_unique<boost::asio::io_service>())
- , m_ioService(*m_internalIoService)
- , m_internalKeyChain(make_unique<KeyChain>())
- , m_impl(make_shared<Impl>(*this))
+ : m_impl(new Impl(*this))
{
- construct(std::move(transport), *m_internalKeyChain);
+ construct(transport, ns3::ndn::StackHelper::getKeyChain());
}
Face::Face(boost::asio::io_service& ioService)
- : m_ioService(ioService)
- , m_internalKeyChain(make_unique<KeyChain>())
- , m_impl(make_shared<Impl>(*this))
+ : m_impl(new Impl(*this))
{
- construct(nullptr, *m_internalKeyChain);
-}
-
-Face::Face(const std::string& host, const std::string& port)
- : m_internalIoService(make_unique<boost::asio::io_service>())
- , m_ioService(*m_internalIoService)
- , m_internalKeyChain(make_unique<KeyChain>())
- , m_impl(make_shared<Impl>(*this))
-{
- construct(make_shared<TcpTransport>(host, port), *m_internalKeyChain);
+ construct(nullptr, ns3::ndn::StackHelper::getKeyChain());
}
Face::Face(shared_ptr<Transport> transport, KeyChain& keyChain)
- : m_internalIoService(make_unique<boost::asio::io_service>())
- , m_ioService(*m_internalIoService)
- , m_impl(make_shared<Impl>(*this))
+ : m_impl(new Impl(*this))
{
construct(std::move(transport), keyChain);
}
Face::Face(shared_ptr<Transport> transport, boost::asio::io_service& ioService)
- : m_ioService(ioService)
- , m_internalKeyChain(make_unique<KeyChain>())
- , m_impl(make_shared<Impl>(*this))
+ : m_impl(new Impl(*this))
{
- construct(std::move(transport), *m_internalKeyChain);
+ construct(transport, ns3::ndn::StackHelper::getKeyChain());
}
Face::Face(shared_ptr<Transport> transport, boost::asio::io_service& ioService, KeyChain& keyChain)
- : m_ioService(ioService)
- , m_impl(make_shared<Impl>(*this))
+ : m_impl(new Impl(*this))
{
construct(std::move(transport), keyChain);
}
@@ -108,46 +95,25 @@
shared_ptr<Transport>
Face::makeDefaultTransport()
{
- // transport=unix:///var/run/nfd.sock
- // transport=tcp://localhost:6363
+ ns3::Ptr<ns3::Node> node = ns3::NodeList::GetNode(ns3::Simulator::GetContext());
+ NS_ASSERT_MSG(node->GetObject<ns3::ndn::L3Protocol>() != 0,
+ "NDN stack should be installed on the node " << node);
- std::string transportUri;
+ auto uri = ::nfd::FaceUri("ndnFace://" + boost::lexical_cast<std::string>(node->GetId()));
- const char* transportEnviron = getenv("NDN_CLIENT_TRANSPORT");
- if (transportEnviron != nullptr) {
- transportUri = transportEnviron;
- }
- else {
- ConfigFile config;
- transportUri = config.getParsedConfiguration().get<std::string>("transport", "");
- }
+ ::nfd::face::GenericLinkService::Options serviceOpts;
+ serviceOpts.allowLocalFields = true;
- if (transportUri.empty()) {
- // transport not specified, use default Unix transport.
- return UnixTransport::create("");
- }
+ auto nfdFace = make_shared<::nfd::Face>(make_unique<::nfd::face::GenericLinkService>(serviceOpts),
+ make_unique<::nfd::face::InternalForwarderTransport>(uri, uri));
+ auto forwarderTransport = static_cast<::nfd::face::InternalForwarderTransport*>(nfdFace->getTransport());
- std::string protocol;
- try {
- FaceUri uri(transportUri);
- protocol = uri.getScheme();
+ auto clientTransport = make_shared<::nfd::face::InternalClientTransport>();
+ clientTransport->connectToForwarder(forwarderTransport);
- if (protocol == "unix") {
- return UnixTransport::create(transportUri);
- }
- else if (protocol == "tcp" || protocol == "tcp4" || protocol == "tcp6") {
- return TcpTransport::create(transportUri);
- }
- else {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unsupported transport protocol \"" + protocol + "\""));
- }
- }
- catch (const Transport::Error& error) {
- BOOST_THROW_EXCEPTION(ConfigFile::Error(error.what()));
- }
- catch (const FaceUri::Error& error) {
- BOOST_THROW_EXCEPTION(ConfigFile::Error(error.what()));
- }
+ node->GetObject<ns3::ndn::L3Protocol>()->addFace(nfdFace);;
+
+ return clientTransport;
}
void
@@ -310,40 +276,6 @@
void
Face::doProcessEvents(time::milliseconds timeout, bool keepThread)
{
- if (m_ioService.stopped()) {
- m_ioService.reset(); // ensure that run()/poll() will do some work
- }
-
- try {
- if (timeout < time::milliseconds::zero()) {
- // do not block if timeout is negative, but process pending events
- m_ioService.poll();
- return;
- }
-
- if (timeout > time::milliseconds::zero()) {
- boost::asio::io_service& ioService = m_ioService;
- unique_ptr<boost::asio::io_service::work>& work = m_impl->m_ioServiceWork;
- m_impl->m_processEventsTimeoutEvent = m_impl->m_scheduler.scheduleEvent(timeout,
- [&ioService, &work] {
- ioService.stop();
- work.reset();
- });
- }
-
- if (keepThread) {
- // work will ensure that m_ioService is running until work object exists
- m_impl->m_ioServiceWork.reset(new boost::asio::io_service::work(m_ioService));
- }
-
- m_ioService.run();
- }
- catch (...) {
- m_impl->m_ioServiceWork.reset();
- m_impl->m_pendingInterestTable.clear();
- m_impl->m_registeredPrefixTable.clear();
- throw;
- }
}
void
@@ -362,8 +294,6 @@
if (m_transport->isConnected())
m_transport->close();
-
- m_impl->m_ioServiceWork.reset();
}
/**
diff --git a/src/face.hpp b/src/face.hpp
index e5ccbba..99f6b5c 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -167,15 +167,6 @@
Face(boost::asio::io_service& ioService);
/**
- * @brief Create Face using TcpTransport
- *
- * @param host IP address or hostname of the NDN forwarder
- * @param port port number or service name of the NDN forwarder (**default**: "6363")
- */
- explicit
- Face(const std::string& host, const std::string& port = "6363");
-
- /**
* @brief Create Face using given transport and KeyChain
* @param transport the transport for lower layer communication. If nullptr,
* a default transport will be used.
@@ -466,12 +457,12 @@
shutdown();
/**
- * @return reference to IO service object
+ * @brief Return nullptr (cannot use IoService in simulations), preserved for API compatibility
*/
boost::asio::io_service&
getIoService()
{
- return m_ioService;
+ return *static_cast<boost::asio::io_service*>(nullptr);
}
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
@@ -506,22 +497,8 @@
asyncShutdown();
private:
- /// the IO service owned by this Face, could be null
- unique_ptr<boost::asio::io_service> m_internalIoService;
- /// the IO service used by this Face
- boost::asio::io_service& m_ioService;
-
shared_ptr<Transport> m_transport;
- /**
- * @brief if not null, a pointer to an internal KeyChain owned by Face
- * @note if a KeyChain is supplied to constructor, this pointer will be null,
- * and the passed KeyChain is given to nfdController;
- * currently Face does not keep the KeyChain passed in constructor
- * because it's not needed, but this may change in the future
- */
- unique_ptr<KeyChain> m_internalKeyChain;
-
unique_ptr<nfd::Controller> m_nfdController;
class Impl;