blob: 1461dbfa5e429bbff460f6e891a7d85116c9c554 [file] [log] [blame]
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -07001/**
2 * @author: Jeff Thompson
3 * See COPYING for copyright and distribution information.
4 */
5
Jeff Thompson48917f02013-08-21 17:12:45 -07006#include <sys/time.h>
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -07007#include "encoding/binary-xml-decoder.hpp"
8#include "c/encoding/binary-xml.h"
Jeff Thompsonb09fcc12013-08-22 10:37:10 -07009#include "node.hpp"
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070010
11using namespace std;
12using namespace ndn::ptr_lib;
13
14namespace ndn {
15
Jeff Thompson48917f02013-08-21 17:12:45 -070016// Use gettimeofday to return the current time in milliseconds.
17static inline double getNowMilliseconds()
Jeff Thompson557b81e2013-08-21 15:13:51 -070018{
Jeff Thompson48917f02013-08-21 17:12:45 -070019 timeval t;
20 gettimeofday(&t, NULL);
21 return t.tv_sec * 1000.0 + t.tv_usec / 1000.0;
22}
Jeff Thompson557b81e2013-08-21 15:13:51 -070023
Jeff Thompson86507bc2013-08-23 20:51:38 -070024void Node::construct()
Jeff Thompson557b81e2013-08-21 15:13:51 -070025{
Jeff Thompson86507bc2013-08-23 20:51:38 -070026 ndndIdFetcherInterest_ = Interest(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0);
Jeff Thompson557b81e2013-08-21 15:13:51 -070027}
28
Jeff Thompson4fe45512013-08-23 14:06:38 -070029void Node::expressInterest(const Interest &interest, const OnData &onData, const OnTimeout &onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070030{
Jeff Thompson86507bc2013-08-23 20:51:38 -070031 // TODO: Properly check if we are already connected to the expected host.
32 if (!transport_->getIsConnected())
33 transport_->connect(*connectionInfo_, *this);
34
Jeff Thompson4fe45512013-08-23 14:06:38 -070035 shared_ptr<PitEntry> pitEntry(new PitEntry(shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout));
Jeff Thompson557b81e2013-08-21 15:13:51 -070036 pit_.push_back(pitEntry);
37
Jeff Thompson48917f02013-08-21 17:12:45 -070038 shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest()->wireEncode();
Jeff Thompson557b81e2013-08-21 15:13:51 -070039
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070040 transport_->send(*encoding);
41}
42
Jeff Thompson4fe45512013-08-23 14:06:38 -070043void Node::expressInterest(const Name &name, const Interest *interestTemplate, const OnData &onData, const OnTimeout &onTimeout)
44{
45 if (interestTemplate)
46 expressInterest(Interest
47 (name, interestTemplate->getMinSuffixComponents(), interestTemplate->getMaxSuffixComponents(),
48 interestTemplate->getPublisherPublicKeyDigest(), interestTemplate->getExclude(),
49 interestTemplate->getChildSelector(), interestTemplate->getAnswerOriginKind(),
50 interestTemplate->getScope(), interestTemplate->getInterestLifetimeMilliseconds()), onData, onTimeout);
51 else
52 expressInterest(Interest(name, 4000.0), onData, onTimeout);
53}
54
Jeff Thompson86507bc2013-08-23 20:51:38 -070055void Node::registerPrefix(const Name &prefix, const OnInterest &onInterest, int flags)
56{
57 if (ndndId_.size() == 0) {
58 // First fetch the ndndId of the connected hub.
59 NdndIdFetcher fetcher(make_shared<NdndIdFetcher::Info>(this, prefix, onInterest, flags));
60 // It is OK for func_lib::function make a copy of the function object because the Info is in a shared_ptr.
61 expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
62 }
63 else
64 registerPrefixHelper(prefix, onInterest, flags);
65}
66
67void Node::NdndIdFetcher::operator()(const ptr_lib::shared_ptr<const Interest> &interest, const ptr_lib::shared_ptr<Data> &ndndIdData)
68{
69 if (ndndIdData->getSignedInfo().getPublisherPublicKeyDigest().getPublisherPublicKeyDigest().size() > 0) {
70 // Set the ndndId_ and continue.
71 info_->node_.ndndId_ = ndndIdData->getSignedInfo().getPublisherPublicKeyDigest().getPublisherPublicKeyDigest();
72 info_->node_.registerPrefixHelper(info_->prefix_, info_->onInterest_, info_->flags_);
73 }
74 // TODO: else need to log not getting the ndndId.
75}
76
77void Node::NdndIdFetcher::operator()(const ptr_lib::shared_ptr<const Interest> &timedOutInterest)
78{
79 // TODO: Log the timeout.
80}
81
82void Node::registerPrefixHelper(const Name &prefix, const OnInterest &onInterest, int flags)
83{
84 throw logic_error("need to finish implementing registerPrefix");
85}
86
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070087void Node::processEvents()
88{
89 transport_->processEvents();
Jeff Thompson48917f02013-08-21 17:12:45 -070090
91 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
92 double nowMilliseconds = getNowMilliseconds();
93 for (int i = (int)pit_.size() - 1; i >= 0; --i) {
94 if (pit_[i]->checkTimeout(this, nowMilliseconds)) {
95 pit_.erase(pit_.begin() + i);
96
97 // Refresh now since the timeout callback might have delayed.
98 nowMilliseconds = getNowMilliseconds();
99 }
100 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700101}
102
Jeff Thompson8b173cc2013-08-21 17:54:12 -0700103void Node::onReceivedElement(const unsigned char *element, unsigned int elementLength)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700104{
105 BinaryXmlDecoder decoder(element, elementLength);
106
107 if (decoder.peekDTag(ndn_BinaryXml_DTag_ContentObject)) {
108 shared_ptr<Data> data(new Data());
109 data->wireDecode(element, elementLength);
110
Jeff Thompson557b81e2013-08-21 15:13:51 -0700111 int iPitEntry = getEntryIndexForExpressedInterest(data->getName());
112 if (iPitEntry >= 0) {
Jeff Thompson7aec0252013-08-22 17:29:57 -0700113 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
114 const OnData onData = pit_[iPitEntry]->getOnData();
115 const ptr_lib::shared_ptr<const Interest> interest = pit_[iPitEntry]->getInterest();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700116 pit_.erase(pit_.begin() + iPitEntry);
Jeff Thompson7aec0252013-08-22 17:29:57 -0700117 onData(interest, data);
Jeff Thompson557b81e2013-08-21 15:13:51 -0700118 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700119 }
120}
121
122void Node::shutdown()
123{
124 transport_->close();
125}
126
Jeff Thompson557b81e2013-08-21 15:13:51 -0700127int Node::getEntryIndexForExpressedInterest(const Name &name)
128{
129 // TODO: Doesn't this belong in the Name class?
130 vector<struct ndn_NameComponent> nameComponents;
131 nameComponents.reserve(name.getComponentCount());
132 struct ndn_Name nameStruct;
133 ndn_Name_init(&nameStruct, &nameComponents[0], nameComponents.capacity());
134 name.get(nameStruct);
135
136 int iResult = -1;
137
138 for (unsigned int i = 0; i < pit_.size(); ++i) {
139 if (ndn_Interest_matchesName((struct ndn_Interest *)&pit_[i]->getInterestStruct(), &nameStruct)) {
140 if (iResult < 0 ||
Jeff Thompson48917f02013-08-21 17:12:45 -0700141 pit_[i]->getInterestStruct().name.nComponents > pit_[iResult]->getInterestStruct().name.nComponents)
142 // Update to the longer match.
Jeff Thompson557b81e2013-08-21 15:13:51 -0700143 iResult = i;
144 }
145 }
146
147 return iResult;
148}
Jeff Thompson86507bc2013-08-23 20:51:38 -0700149
150Node::PitEntry::PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, const OnData &onData, const OnTimeout &onTimeout)
151: interest_(interest), onData_(onData), onTimeout_(onTimeout)
152{
153 // Set up timeoutTime_.
154 if (interest_->getInterestLifetimeMilliseconds() >= 0.0)
155 timeoutTimeMilliseconds_ = getNowMilliseconds() + interest_->getInterestLifetimeMilliseconds();
156 else
157 // No timeout.
158 timeoutTimeMilliseconds_ = -1.0;
159
160 // Set up interestStruct_.
161 // TODO: Doesn't this belong in the Interest class?
162 nameComponents_.reserve(interest_->getName().getComponentCount());
163 excludeEntries_.reserve(interest_->getExclude().getEntryCount());
164 ndn_Interest_init
165 (&interestStruct_, &nameComponents_[0], nameComponents_.capacity(), &excludeEntries_[0], excludeEntries_.capacity());
166 interest_->get(interestStruct_);
167}
168
169bool Node::PitEntry::checkTimeout(Node *parent, double nowMilliseconds)
170{
171 if (timeoutTimeMilliseconds_ >= 0.0 && nowMilliseconds >= timeoutTimeMilliseconds_) {
172 if (onTimeout_) {
173 // Ignore all exceptions.
174 try {
175 onTimeout_(interest_);
176 }
177 catch (...) { }
178 }
179
180 return true;
181 }
182 else
183 return false;
184}
Jeff Thompson557b81e2013-08-21 15:13:51 -0700185
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700186}