blob: 802b84a4392c4e0cfb059d8c04a729f20cf45777 [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"
9#include "data.hpp"
Jeff Thompsonb09fcc12013-08-22 10:37:10 -070010#include "node.hpp"
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070011
12using namespace std;
13using namespace ndn::ptr_lib;
14
15namespace ndn {
16
Jeff Thompson48917f02013-08-21 17:12:45 -070017// Use gettimeofday to return the current time in milliseconds.
18static inline double getNowMilliseconds()
Jeff Thompson557b81e2013-08-21 15:13:51 -070019{
Jeff Thompson48917f02013-08-21 17:12:45 -070020 timeval t;
21 gettimeofday(&t, NULL);
22 return t.tv_sec * 1000.0 + t.tv_usec / 1000.0;
23}
24
Jeff Thompson7aec0252013-08-22 17:29:57 -070025Node::PitEntry::PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, const OnData &onData, const OnTimeout &onTimeout)
26: interest_(interest), onData_(onData), onTimeout_(onTimeout)
Jeff Thompson48917f02013-08-21 17:12:45 -070027{
28 // Set up timeoutTime_.
29 if (interest_->getInterestLifetimeMilliseconds() >= 0.0)
30 timeoutTimeMilliseconds_ = getNowMilliseconds() + interest_->getInterestLifetimeMilliseconds();
Jeff Thompson557b81e2013-08-21 15:13:51 -070031 else
32 // No timeout.
Jeff Thompson48917f02013-08-21 17:12:45 -070033 timeoutTimeMilliseconds_ = -1.0;
34
35 // Set up interestStruct_.
36 // TODO: Doesn't this belong in the Interest class?
37 nameComponents_.reserve(interest_->getName().getComponentCount());
38 excludeEntries_.reserve(interest_->getExclude().getEntryCount());
39 ndn_Interest_init
40 (&interestStruct_, &nameComponents_[0], nameComponents_.capacity(), &excludeEntries_[0], excludeEntries_.capacity());
41 interest_->get(interestStruct_);
Jeff Thompson557b81e2013-08-21 15:13:51 -070042}
43
Jeff Thompson48917f02013-08-21 17:12:45 -070044bool Node::PitEntry::checkTimeout(Node *parent, double nowMilliseconds)
Jeff Thompson557b81e2013-08-21 15:13:51 -070045{
Jeff Thompson48917f02013-08-21 17:12:45 -070046 if (timeoutTimeMilliseconds_ >= 0.0 && nowMilliseconds >= timeoutTimeMilliseconds_) {
Jeff Thompson7aec0252013-08-22 17:29:57 -070047 if (onTimeout_) {
48 // Ignore all exceptions.
49 try {
50 onTimeout_(interest_);
51 }
52 catch (...) { }
Jeff Thompson48917f02013-08-21 17:12:45 -070053 }
Jeff Thompson48917f02013-08-21 17:12:45 -070054
55 return true;
Jeff Thompson557b81e2013-08-21 15:13:51 -070056 }
Jeff Thompson48917f02013-08-21 17:12:45 -070057 else
58 return false;
Jeff Thompson557b81e2013-08-21 15:13:51 -070059}
60
Jeff Thompson7aec0252013-08-22 17:29:57 -070061void Node::expressInterest(const Name &name, const Interest *interestTemplate, const OnData &onData, const OnTimeout &onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070062{
Jeff Thompson48917f02013-08-21 17:12:45 -070063 shared_ptr<const Interest> interest;
64 if (interestTemplate)
65 interest.reset(new Interest
66 (name, interestTemplate->getMinSuffixComponents(), interestTemplate->getMaxSuffixComponents(),
67 interestTemplate->getPublisherPublicKeyDigest(), interestTemplate->getExclude(),
68 interestTemplate->getChildSelector(), interestTemplate->getAnswerOriginKind(),
69 interestTemplate->getScope(), interestTemplate->getInterestLifetimeMilliseconds()));
Jeff Thompson557b81e2013-08-21 15:13:51 -070070 else
Jeff Thompson48917f02013-08-21 17:12:45 -070071 interest.reset(new Interest(name, 4000.0));
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070072
Jeff Thompson7aec0252013-08-22 17:29:57 -070073 shared_ptr<PitEntry> pitEntry(new PitEntry(interest, onData, onTimeout));
Jeff Thompson557b81e2013-08-21 15:13:51 -070074 pit_.push_back(pitEntry);
75
Jeff Thompson48917f02013-08-21 17:12:45 -070076 shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest()->wireEncode();
Jeff Thompson557b81e2013-08-21 15:13:51 -070077
Jeff Thompsona4056972013-08-22 11:52:21 -070078 // TODO: Properly check if we are already connected to the expected host.
79 if (!transport_->getIsConnected())
Jeff Thompson10e34382013-08-22 13:34:46 -070080 transport_->connect(*connectionInfo_, *this);
Jeff Thompsona4056972013-08-22 11:52:21 -070081
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070082 transport_->send(*encoding);
83}
84
85void Node::processEvents()
86{
87 transport_->processEvents();
Jeff Thompson48917f02013-08-21 17:12:45 -070088
89 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
90 double nowMilliseconds = getNowMilliseconds();
91 for (int i = (int)pit_.size() - 1; i >= 0; --i) {
92 if (pit_[i]->checkTimeout(this, nowMilliseconds)) {
93 pit_.erase(pit_.begin() + i);
94
95 // Refresh now since the timeout callback might have delayed.
96 nowMilliseconds = getNowMilliseconds();
97 }
98 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070099}
100
Jeff Thompson8b173cc2013-08-21 17:54:12 -0700101void Node::onReceivedElement(const unsigned char *element, unsigned int elementLength)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700102{
103 BinaryXmlDecoder decoder(element, elementLength);
104
105 if (decoder.peekDTag(ndn_BinaryXml_DTag_ContentObject)) {
106 shared_ptr<Data> data(new Data());
107 data->wireDecode(element, elementLength);
108
Jeff Thompson557b81e2013-08-21 15:13:51 -0700109 int iPitEntry = getEntryIndexForExpressedInterest(data->getName());
110 if (iPitEntry >= 0) {
Jeff Thompson7aec0252013-08-22 17:29:57 -0700111 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
112 const OnData onData = pit_[iPitEntry]->getOnData();
113 const ptr_lib::shared_ptr<const Interest> interest = pit_[iPitEntry]->getInterest();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700114 pit_.erase(pit_.begin() + iPitEntry);
Jeff Thompson7aec0252013-08-22 17:29:57 -0700115 onData(interest, data);
Jeff Thompson557b81e2013-08-21 15:13:51 -0700116 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700117 }
118}
119
120void Node::shutdown()
121{
122 transport_->close();
123}
124
Jeff Thompson557b81e2013-08-21 15:13:51 -0700125int Node::getEntryIndexForExpressedInterest(const Name &name)
126{
127 // TODO: Doesn't this belong in the Name class?
128 vector<struct ndn_NameComponent> nameComponents;
129 nameComponents.reserve(name.getComponentCount());
130 struct ndn_Name nameStruct;
131 ndn_Name_init(&nameStruct, &nameComponents[0], nameComponents.capacity());
132 name.get(nameStruct);
133
134 int iResult = -1;
135
136 for (unsigned int i = 0; i < pit_.size(); ++i) {
137 if (ndn_Interest_matchesName((struct ndn_Interest *)&pit_[i]->getInterestStruct(), &nameStruct)) {
138 if (iResult < 0 ||
Jeff Thompson48917f02013-08-21 17:12:45 -0700139 pit_[i]->getInterestStruct().name.nComponents > pit_[iResult]->getInterestStruct().name.nComponents)
140 // Update to the longer match.
Jeff Thompson557b81e2013-08-21 15:13:51 -0700141 iResult = i;
142 }
143 }
144
145 return iResult;
146}
147
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700148}