[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 fb6642a..5ebec16 100644
--- a/src/detail/face-impl.hpp
+++ b/src/detail/face-impl.hpp
@@ -40,6 +40,13 @@
#include "../management/nfd-controller.hpp"
#include "../management/nfd-command-options.hpp"
+#include <ns3/ptr.h>
+#include <ns3/node.h>
+#include <ns3/node-list.h>
+#include <ns3/ndnSIM/model/ndn-l3-protocol.hpp>
+
+#include "ns3/ndnSIM/NFD/daemon/face/local-face.hpp"
+
namespace ndn {
class Face::Impl : noncopyable
@@ -49,29 +56,80 @@
typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
typedef ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>> RegisteredPrefixTable;
+ class NfdFace : public ::nfd::LocalFace
+ {
+ public:
+ NfdFace(Impl& face, const ::nfd::FaceUri& localUri, const ::nfd::FaceUri& remoteUri)
+ : ::nfd::LocalFace(localUri, remoteUri)
+ , m_appFaceImpl(face)
+ {
+ }
+
+ public: // from ::nfd::LocalFace
+ /**
+ * @brief Send Interest towards application
+ */
+ virtual void
+ sendInterest(const Interest& interest)
+ {
+ NS_LOG_DEBUG("<< Interest " << interest);
+ shared_ptr<const Interest> interestPtr = interest.shared_from_this();
+ m_appFaceImpl.m_scheduler.scheduleEvent(time::seconds(0), [this, interestPtr] {
+ m_appFaceImpl.processInterestFilters(*interestPtr);
+ });
+ }
+
+ /**
+ * @brief Send Data towards application
+ */
+ virtual void
+ sendData(const Data& data)
+ {
+ NS_LOG_DEBUG("<< Data " << data.getName());
+ shared_ptr<const Data> dataPtr = data.shared_from_this();
+ m_appFaceImpl.m_scheduler.scheduleEvent(time::seconds(0), [this, dataPtr] {
+ m_appFaceImpl.satisfyPendingInterests(*dataPtr);
+ });
+ }
+
+ /** \brief Close the face
+ *
+ * This terminates all communication on the face and cause
+ * onFail() method event to be invoked
+ */
+ virtual void
+ close()
+ {
+ this->fail("close");
+ }
+
+ private:
+ friend class Impl;
+ Impl& m_appFaceImpl;
+ };
+
+ ////////////////////////////////////////////////////////////////////////
+
explicit
Impl(Face& face)
: m_face(face)
, m_scheduler(m_face.getIoService())
- , m_processEventsTimeoutEvent(m_scheduler)
{
- auto postOnEmptyPitOrNoRegisteredPrefixes = [this] {
- this->m_face.getIoService().post(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
- // async_read duplications can cause various effects and result in segfault.
- };
+ 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);
- m_pendingInterestTable.onEmpty.connect(postOnEmptyPitOrNoRegisteredPrefixes);
- m_registeredPrefixTable.onEmpty.connect(postOnEmptyPitOrNoRegisteredPrefixes);
+ auto uri = ::nfd::FaceUri("ndnFace://" + boost::lexical_cast<std::string>(node->GetId()));
+ m_nfdFace = make_shared<NfdFace>(*this, uri, uri);
+
+ node->GetObject<ns3::ndn::L3Protocol>()->addFace(m_nfdFace);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
void
- satisfyPendingInterests(Data& data)
+ satisfyPendingInterests(const Data& data)
{
for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
if ((*entry)->getInterest().matchesData(data)) {
@@ -87,7 +145,7 @@
}
void
- processInterestFilters(Interest& interest)
+ processInterestFilters(const Interest& interest)
{
for (const auto& filter : m_interestFilterTable) {
if (filter->doesMatch(interest.getName())) {
@@ -100,37 +158,16 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
void
- ensureConnected(bool wantResume)
- {
- if (!m_face.m_transport->isConnected())
- m_face.m_transport->connect(m_face.m_ioService,
- bind(&Face::onReceiveElement, &m_face, _1));
-
- if (wantResume && !m_face.m_transport->isExpectingData())
- m_face.m_transport->resume();
- }
-
- void
asyncExpressInterest(const shared_ptr<const Interest>& interest,
const OnData& onData, const OnTimeout& onTimeout)
{
- this->ensureConnected(true);
-
auto entry =
m_pendingInterestTable.insert(make_shared<PendingInterest>(interest,
onData, onTimeout,
ref(m_scheduler))).first;
(*entry)->setDeleter([this, entry] { m_pendingInterestTable.erase(entry); });
- if (!interest->getLocalControlHeader().empty(nfd::LocalControlHeader::ENCODE_NEXT_HOP)) {
- // encode only NextHopFaceId towards the forwarder
- m_face.m_transport->send(interest->getLocalControlHeader()
- .wireEncode(*interest, nfd::LocalControlHeader::ENCODE_NEXT_HOP),
- interest->wireEncode());
- }
- else {
- m_face.m_transport->send(interest->wireEncode());
- }
+ m_nfdFace->emitSignal(onReceiveInterest, *interest);
}
void
@@ -142,17 +179,7 @@
void
asyncPutData(const shared_ptr<const Data>& data)
{
- this->ensureConnected(true);
-
- if (!data->getLocalControlHeader().empty(nfd::LocalControlHeader::ENCODE_CACHING_POLICY)) {
- m_face.m_transport->send(
- data->getLocalControlHeader().wireEncode(*data,
- nfd::LocalControlHeader::ENCODE_CACHING_POLICY),
- data->wireEncode());
- }
- else {
- m_face.m_transport->send(data->wireEncode());
- }
+ m_nfdFace->emitSignal(onReceiveData, *data);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -266,27 +293,15 @@
}
}
- void
- onEmptyPitOrNoRegisteredPrefixes()
- {
- if (m_pendingInterestTable.empty() && m_registeredPrefixTable.empty()) {
- m_face.m_transport->pause();
- if (!m_ioServiceWork) {
- m_processEventsTimeoutEvent.cancel();
- }
- }
- }
-
private:
Face& m_face;
util::Scheduler m_scheduler;
- util::scheduler::ScopedEventId m_processEventsTimeoutEvent;
PendingInterestTable m_pendingInterestTable;
InterestFilterTable m_interestFilterTable;
RegisteredPrefixTable m_registeredPrefixTable;
- unique_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
+ shared_ptr<NfdFace> m_nfdFace;
friend class Face;
};
diff --git a/src/detail/pending-interest.hpp b/src/detail/pending-interest.hpp
index 41f6b37..9cea52c 100644
--- a/src/detail/pending-interest.hpp
+++ b/src/detail/pending-interest.hpp
@@ -76,9 +76,9 @@
* @note If the DataCallback is an empty function, this method does nothing.
*/
void
- invokeDataCallback(Data& data)
+ invokeDataCallback(const Data& data)
{
- m_onData(*m_interest, data);
+ m_onData(*m_interest, const_cast<Data&>(data));
}
/**