Finish implementing registerPrefix.
diff --git a/ndn-cpp/node.cpp b/ndn-cpp/node.cpp
index a93ebd7..6a60e3b 100644
--- a/ndn-cpp/node.cpp
+++ b/ndn-cpp/node.cpp
@@ -6,6 +6,8 @@
#include <sys/time.h>
#include "encoding/binary-xml-decoder.hpp"
#include "c/encoding/binary-xml.h"
+#include "forwarding-entry.hpp"
+#include "security/key-chain.hpp"
#include "node.hpp"
using namespace std;
@@ -33,11 +35,9 @@
if (!transport_->getIsConnected())
transport_->connect(*connectionInfo_, *this);
- shared_ptr<PitEntry> pitEntry(new PitEntry(shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout));
- pit_.push_back(pitEntry);
+ pit_.push_back(shared_ptr<PitEntry>(new PitEntry(shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout)));
- shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest()->wireEncode();
-
+ shared_ptr<vector<unsigned char> > encoding = interest.wireEncode();
transport_->send(*encoding);
}
@@ -71,7 +71,35 @@
void Node::registerPrefixHelper(const Name &prefix, const OnInterest &onInterest, int flags)
{
- throw logic_error("need to finish implementing registerPrefix");
+ // Create a ForwardingEntry.
+ ForwardingEntry forwardingEntry("selfreg", prefix, PublisherPublicKeyDigest(), -1, 3, 2147483647);
+ ptr_lib::shared_ptr<vector<unsigned char> > content = forwardingEntry.wireEncode();
+
+ // Set the ForwardingEntry as the content of a Data packet and sign.
+ Data data;
+ data.setContent(*content);
+ data.getSignedInfo().setTimestampMilliseconds(time(NULL) * 1000.0);
+ // TODO: Should we sign with a different key?
+ KeyChain::defaultSign(data);
+ ptr_lib::shared_ptr<vector<unsigned char> > encodedData = data.wireEncode();
+
+ // Create an interest where the name has the encoded Data packet.
+ Name interestName;
+ const unsigned char component0[] = "ndnx";
+ const unsigned char component2[] = "selfreg";
+ interestName.addComponent(component0, sizeof(component0) - 1);
+ interestName.addComponent(ndndId_);
+ interestName.addComponent(component2, sizeof(component2) - 1);
+ interestName.addComponent(*encodedData);
+
+ Interest interest(interestName);
+ interest.setScope(1);
+ ptr_lib::shared_ptr<vector<unsigned char> > encodedInterest = interest.wireEncode();
+
+ // Save the onInterest callback and send the registration interest.
+ registeredPrefixTable_.push_back(shared_ptr<PrefixEntry>(new PrefixEntry(shared_ptr<const Name>(new Name(prefix)), onInterest)));
+
+ transport_->send(*encodedInterest);
}
void Node::processEvents()
@@ -94,7 +122,15 @@
{
BinaryXmlDecoder decoder(element, elementLength);
- if (decoder.peekDTag(ndn_BinaryXml_DTag_ContentObject)) {
+ if (decoder.peekDTag(ndn_BinaryXml_DTag_Interest)) {
+ shared_ptr<Interest> interest(new Interest());
+ interest->wireDecode(element, elementLength);
+
+ PrefixEntry *entry = getEntryForRegisteredPrefix(interest->getName());
+ if (entry)
+ entry->getOnInterest()(entry->getPrefix(), interest, *transport_);
+ }
+ else if (decoder.peekDTag(ndn_BinaryXml_DTag_ContentObject)) {
shared_ptr<Data> data(new Data());
data->wireDecode(element, elementLength);
@@ -137,6 +173,25 @@
return iResult;
}
+Node::PrefixEntry *Node::getEntryForRegisteredPrefix(const Name &name)
+{
+ int iResult = -1;
+
+ for (unsigned int i = 0; i < pit_.size(); ++i) {
+ if (registeredPrefixTable_[i]->getPrefix()->match(name)) {
+ if (iResult < 0 ||
+ registeredPrefixTable_[i]->getPrefix()->getComponentCount() > registeredPrefixTable_[iResult]->getPrefix()->getComponentCount())
+ // Update to the longer match.
+ iResult = i;
+ }
+ }
+
+ if (iResult >= 0)
+ return registeredPrefixTable_[iResult].get();
+ else
+ return 0;
+}
+
Node::PitEntry::PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, const OnData &onData, const OnTimeout &onTimeout)
: interest_(interest), onData_(onData), onTimeout_(onTimeout)
{
diff --git a/ndn-cpp/node.hpp b/ndn-cpp/node.hpp
index 8bd59c2..b82ba8a 100644
--- a/ndn-cpp/node.hpp
+++ b/ndn-cpp/node.hpp
@@ -27,7 +27,8 @@
/**
* An OnInterest function object is used to pass a callback to registerPrefix.
*/
-typedef func_lib::function<void(const ptr_lib::shared_ptr<const Name> &, const ptr_lib::shared_ptr<const Interest> &)> OnInterest;
+typedef func_lib::function<void
+ (const ptr_lib::shared_ptr<const Name> &, const ptr_lib::shared_ptr<const Interest> &, Transport &)> OnInterest;
class Face;
@@ -82,10 +83,8 @@
/**
* Create a new PitEntry and set the timeoutTime_ based on the current time and the interest lifetime.
* @param interest A shared_ptr for the interest.
- * @param onData A function object to call when a matching data packet is received. This copies the function object, so you may need to
- * use func_lib::ref() as appropriate.
+ * @param onData A function object to call when a matching data packet is received.
* @param onTimeout A function object to call if the interest times out. If onTimeout is an empty OnTimeout(), this does not use it.
- * This copies the function object, so you may need to use func_lib::ref() as appropriate.
*/
PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, const OnData &onData, const OnTimeout &onTimeout);
@@ -124,6 +123,27 @@
const OnTimeout onTimeout_;
double timeoutTimeMilliseconds_; /**< The time when the interest times out in milliseconds according to gettimeofday, or -1 for no timeout. */
};
+
+ class PrefixEntry {
+ public:
+ /**
+ * Create a new PrefixEntry.
+ * @param prefix A shared_ptr for the prefix.
+ * @param onInterest A function object to call when a matching data packet is received.
+ */
+ PrefixEntry(const ptr_lib::shared_ptr<const Name> &prefix, const OnInterest &onInterest)
+ : prefix_(prefix), onInterest_(onInterest)
+ {
+ }
+
+ const ptr_lib::shared_ptr<const Name> &getPrefix() { return prefix_; }
+
+ const OnInterest &getOnInterest() { return onInterest_; }
+
+ private:
+ ptr_lib::shared_ptr<const Name> prefix_;
+ const OnInterest onInterest_;
+ };
/**
* An NdndIdFetcher receives the Data packet with the publisher public key digest for the connected NDN hub.
@@ -176,6 +196,13 @@
int getEntryIndexForExpressedInterest(const Name &name);
/**
+ * Find the first entry from the registeredPrefixTable_ where the entry prefix is the longest that matches name.
+ * @param name The name to find the PrefixEntry for (from the incoming interest packet).
+ * @return A pointer to the entry, or 0 if not found.
+ */
+ PrefixEntry *getEntryForRegisteredPrefix(const Name &name);
+
+ /**
* Do the work of registerPrefix once we know we are connected with an ndndId_.
* @param prefix
* @param onInterest
@@ -186,6 +213,7 @@
ptr_lib::shared_ptr<Transport> transport_;
ptr_lib::shared_ptr<const Transport::ConnectionInfo> connectionInfo_;
std::vector<ptr_lib::shared_ptr<PitEntry> > pit_;
+ std::vector<ptr_lib::shared_ptr<PrefixEntry> > registeredPrefixTable_;
Interest ndndIdFetcherInterest_;
std::vector<unsigned char> ndndId_;
};
diff --git a/tests/test-publish-async.cpp b/tests/test-publish-async.cpp
index 78bc12b..5358169 100644
--- a/tests/test-publish-async.cpp
+++ b/tests/test-publish-async.cpp
@@ -22,17 +22,20 @@
interestCount_ = 0;
}
- void operator()(const ptr_lib::shared_ptr<const Name> &prefix, const ptr_lib::shared_ptr<const Interest> &interest) {
+ void operator()
+ (const ptr_lib::shared_ptr<const Name> &prefix, const ptr_lib::shared_ptr<const Interest> &interest, Transport &transport) {
++interestCount_;
// Make and sign a Data packet.
Data data(interest->getName());
string content(string("Echo ") + interest->getName().toUri());
- data.setContent((const unsigned char*)&content[0], sizeof(content));
+ data.setContent((const unsigned char *)&content[0], content.size());
data.getSignedInfo().setTimestampMilliseconds(time(NULL) * 1000.0);
KeyChain::defaultSign(data);
+ shared_ptr<vector<unsigned char> > encodedData = data.wireEncode();
- // TODO: Need to put the Data.
+ cout << "Sent content " << content << endl;
+ transport.send(*encodedData);
}
int interestCount_;
@@ -48,7 +51,8 @@
cout << "Register prefix " << prefix.toUri() << endl;
face.registerPrefix(prefix, ref(echo));
- // The main event loop.
+ // The main event loop.
+ // Wait forever to receive one interest for the prefix.
while (echo.interestCount_ < 1) {
face.processEvents();
// We need to sleep for a few milliseconds so we don't use 100% of the CPU.