hello-protocol.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
20 #include "hello-protocol.hpp"
21 
22 #include "hello-protocol.hpp"
23 #include "nlsr.hpp"
24 #include "lsdb.hpp"
25 #include "utility/name-helper.hpp"
26 #include "logger.hpp"
27 
28 namespace nlsr {
29 
30 INIT_LOGGER(HelloProtocol);
31 
32 const std::string HelloProtocol::INFO_COMPONENT = "INFO";
33 const std::string HelloProtocol::NLSR_COMPONENT = "nlsr";
34 
35 HelloProtocol::HelloProtocol(ndn::Face& face, ndn::KeyChain& keyChain,
36  ndn::security::SigningInfo& signingInfo,
37  ConfParameter& confParam, RoutingTable& routingTable,
38  Lsdb& lsdb)
39  : m_face(face)
40  , m_scheduler(m_face.getIoService())
41  , m_keyChain(keyChain)
42  , m_signingInfo(signingInfo)
43  , m_confParam(confParam)
44  , m_routingTable(routingTable)
45  , m_lsdb(lsdb)
46 {
47 }
48 
49 void
50 HelloProtocol::expressInterest(const ndn::Name& interestName, uint32_t seconds)
51 {
52  NLSR_LOG_DEBUG("Expressing Interest :" << interestName);
53  ndn::Interest interest(interestName);
54  interest.setInterestLifetime(ndn::time::seconds(seconds));
55  interest.setMustBeFresh(true);
56  interest.setCanBePrefix(true);
57  m_face.expressInterest(interest,
58  std::bind(&HelloProtocol::onContent, this, _1, _2),
59  [this] (const ndn::Interest& interest, const ndn::lp::Nack& nack)
60  {
61  NDN_LOG_TRACE("Received Nack with reason " << nack.getReason());
62  NDN_LOG_TRACE("Treating as timeout");
63  processInterestTimedOut(interest);
64  },
65  std::bind(&HelloProtocol::processInterestTimedOut, this, _1));
66 
67  // increment SENT_HELLO_INTEREST
69 }
70 
71 void
73 {
74  for (const auto& adjacent : m_confParam.getAdjacencyList().getAdjList()) {
75  // If this adjacency has a Face, just proceed as usual.
76  if(adjacent.getFaceId() != 0) {
77  // interest name: /<neighbor>/NLSR/INFO/<router>
78  ndn::Name interestName = adjacent.getName() ;
79  interestName.append(NLSR_COMPONENT);
80  interestName.append(INFO_COMPONENT);
81  interestName.append(m_confParam.getRouterPrefix().wireEncode());
82  expressInterest(interestName, m_confParam.getInterestResendTime());
83  NLSR_LOG_DEBUG("Sending scheduled interest: " << interestName);
84  }
85  }
87 }
88 
89 void
91 {
92  NLSR_LOG_DEBUG("Scheduling HELLO Interests in " << ndn::time::seconds(seconds));
93 
94  m_scheduler.scheduleEvent(ndn::time::seconds(seconds),
95  [this] {
97  });
98 }
99 
100 void
101 HelloProtocol::processInterest(const ndn::Name& name,
102  const ndn::Interest& interest)
103 {
104  // interest name: /<neighbor>/NLSR/INFO/<router>
105  const ndn::Name interestName = interest.getName();
106 
107  // increment RCV_HELLO_INTEREST
109 
110  NLSR_LOG_DEBUG("Interest Received for Name: " << interestName);
111  if (interestName.get(-2).toUri() != INFO_COMPONENT) {
112  NLSR_LOG_DEBUG("INFO_COMPONENT not found or interestName: " << interestName
113  << " does not match expression");
114  return;
115  }
116 
117  ndn::Name neighbor;
118  neighbor.wireDecode(interestName.get(-1).blockFromValue());
119  NLSR_LOG_DEBUG("Neighbor: " << neighbor);
120  if (m_confParam.getAdjacencyList().isNeighbor(neighbor)) {
121  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
122  data->setName(ndn::Name(interest.getName()).appendVersion());
123  data->setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
124  data->setContent(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.c_str()),
125  INFO_COMPONENT.size());
126 
127  m_keyChain.sign(*data, m_signingInfo);
128 
129  NLSR_LOG_DEBUG("Sending out data for name: " << interest.getName());
130 
131  m_face.put(*data);
132  // increment SENT_HELLO_DATA
134 
135  auto adjacent = m_confParam.getAdjacencyList().findAdjacent(neighbor);
136  // If this neighbor was previously inactive, send our own hello interest, too
137  if (adjacent->getStatus() == Adjacent::STATUS_INACTIVE) {
138  // We can only do that if the neighbor currently has a face.
139  if(adjacent->getFaceId() != 0){
140  // interest name: /<neighbor>/NLSR/INFO/<router>
141  ndn::Name interestName(neighbor);
142  interestName.append(NLSR_COMPONENT);
143  interestName.append(INFO_COMPONENT);
144  interestName.append(m_confParam.getRouterPrefix().wireEncode());
145  expressInterest(interestName, m_confParam.getInterestResendTime());
146  }
147  }
148  }
149 }
150 
151 void
152 HelloProtocol::processInterestTimedOut(const ndn::Interest& interest)
153 {
154  // interest name: /<neighbor>/NLSR/INFO/<router>
155  const ndn::Name interestName(interest.getName());
156  NLSR_LOG_DEBUG("Interest timed out for Name: " << interestName);
157  if (interestName.get(-2).toUri() != INFO_COMPONENT) {
158  return;
159  }
160  ndn::Name neighbor = interestName.getPrefix(-3);
161  NLSR_LOG_DEBUG("Neighbor: " << neighbor);
162  m_confParam.getAdjacencyList().incrementTimedOutInterestCount(neighbor);
163 
164  Adjacent::Status status = m_confParam.getAdjacencyList().getStatusOfNeighbor(neighbor);
165 
166  uint32_t infoIntTimedOutCount =
167  m_confParam.getAdjacencyList().getTimedOutInterestCount(neighbor);
168  NLSR_LOG_DEBUG("Status: " << status);
169  NLSR_LOG_DEBUG("Info Interest Timed out: " << infoIntTimedOutCount);
170  if (infoIntTimedOutCount < m_confParam.getInterestRetryNumber()) {
171  // interest name: /<neighbor>/NLSR/INFO/<router>
172  ndn::Name interestName(neighbor);
173  interestName.append(NLSR_COMPONENT);
174  interestName.append(INFO_COMPONENT);
175  interestName.append(m_confParam.getRouterPrefix().wireEncode());
176  NLSR_LOG_DEBUG("Resending interest: " << interestName);
177  expressInterest(interestName, m_confParam.getInterestResendTime());
178  }
179  else if ((status == Adjacent::STATUS_ACTIVE) &&
180  (infoIntTimedOutCount == m_confParam.getInterestRetryNumber())) {
182 
183  NLSR_LOG_DEBUG("Neighbor: " << neighbor << " status changed to INACTIVE");
184 
185  m_lsdb.scheduleAdjLsaBuild();
186  }
187 }
188 
189  // This is the first function that incoming Hello data will
190  // see. This checks if the data appears to be signed, and passes it
191  // on to validate the content of the data.
192 void
193 HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
194 {
195  NLSR_LOG_DEBUG("Received data for INFO(name): " << data.getName());
196  if (data.getSignature().hasKeyLocator()) {
197  if (data.getSignature().getKeyLocator().getType() == ndn::KeyLocator::KeyLocator_Name) {
198  NLSR_LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
199  }
200  }
201  m_confParam.getValidator().validate(data,
202  std::bind(&HelloProtocol::onContentValidated, this, _1),
203  std::bind(&HelloProtocol::onContentValidationFailed,
204  this, _1, _2));
205 }
206 
207 void
208 HelloProtocol::onContentValidated(const ndn::Data& data)
209 {
210  // data name: /<neighbor>/NLSR/INFO/<router>/<version>
211  ndn::Name dataName = data.getName();
212  NLSR_LOG_DEBUG("Data validation successful for INFO(name): " << dataName);
213 
214  if (dataName.get(-3).toUri() == INFO_COMPONENT) {
215  ndn::Name neighbor = dataName.getPrefix(-4);
216 
217  Adjacent::Status oldStatus = m_confParam.getAdjacencyList().getStatusOfNeighbor(neighbor);
219  m_confParam.getAdjacencyList().setTimedOutInterestCount(neighbor, 0);
220  Adjacent::Status newStatus = m_confParam.getAdjacencyList().getStatusOfNeighbor(neighbor);
221 
222  NLSR_LOG_DEBUG("Neighbor : " << neighbor);
223  NLSR_LOG_DEBUG("Old Status: " << oldStatus << " New Status: " << newStatus);
224  // change in Adjacency list
225  if ((oldStatus - newStatus) != 0) {
226  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
227  m_routingTable.scheduleRoutingTableCalculation();
228  }
229  else {
230  m_lsdb.scheduleAdjLsaBuild();
231  }
232  }
233  }
234  // increment RCV_HELLO_DATA
236 }
237 
238 void
239 HelloProtocol::onContentValidationFailed(const ndn::Data& data,
240  const ndn::security::v2::ValidationError& ve)
241 {
242  NLSR_LOG_DEBUG("Validation Error: " << ve);
243 }
244 
245 } // namespace nlsr
uint32_t getInterestResendTime() const
void setTimedOutInterestCount(const ndn::Name &neighbor, uint32_t count)
ndn::security::ValidatorConfig & getValidator()
A class to house all the configuration parameters for NLSR.
void scheduleAdjLsaBuild()
Schedules a build of this router&#39;s LSA.
Definition: lsdb.cpp:581
ndn::util::signal::Signal< HelloProtocol, Statistics::PacketType > hpIncrementSignal
void scheduleRoutingTableCalculation()
Schedules a calculation event in the event scheduler only if one isn&#39;t already scheduled.
bool isNeighbor(const ndn::Name &adjName) const
AdjacencyList & getAdjacencyList()
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
uint32_t getInfoInterestInterval() const
const ndn::Name & getRouterPrefix() const
Adjacent::Status getStatusOfNeighbor(const ndn::Name &neighbor) const
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
void expressInterest(const ndn::Name &interestNamePrefix, uint32_t seconds)
Sends a Hello Interest packet.
HelloProtocol(ndn::Face &face, ndn::KeyChain &keyChain, ndn::security::SigningInfo &signingInfo, ConfParameter &confParam, RoutingTable &routingTable, Lsdb &lsdb)
void scheduleInterest(uint32_t seconds)
Schedules a Hello Interest event.
#define INIT_LOGGER(name)
Definition: logger.hpp:35
uint32_t getInterestRetryNumber() const
void processInterest(const ndn::Name &name, const ndn::Interest &interest)
Processes a Hello Interest from a neighbor.
int32_t getTimedOutInterestCount(const ndn::Name &neighbor) const
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California, Arizona Board of Regents.
AdjacencyList::iterator findAdjacent(const ndn::Name &adjName)
int32_t getHyperbolicState() const
void sendScheduledInterest()
Sends Hello Interests to all neighbors.
void incrementTimedOutInterestCount(const ndn::Name &neighbor)
std::list< Adjacent > & getAdjList()
void setStatusOfNeighbor(const ndn::Name &neighbor, Adjacent::Status status)