blob: 4a995deb488788f79052580dce08290e5661cec2 [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Nick Gordonfeae5572017-01-13 12:06:26 -06003 * Copyright (c) 2014-2017, The University of Memphis,
Nick Gordonf8b5bcd2016-08-11 15:06:50 -05004 * Regents of the University of California
akmhoque3d06e792014-05-27 16:23:20 -05005 *
6 * This file is part of NLSR (Named-data Link State Routing).
7 * See AUTHORS.md for complete list of NLSR authors and contributors.
8 *
9 * NLSR is free software: you can redistribute it and/or modify it under the terms
10 * of the GNU General Public License as published by the Free Software Foundation,
11 * either version 3 of the License, or (at your option) any later version.
12 *
13 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
19 *
akmhoque3d06e792014-05-27 16:23:20 -050020 **/
Junxiao Shi63bd0342016-08-17 16:57:14 +000021
akmhoque31d1d4b2014-05-05 22:08:14 -050022#include "nlsr.hpp"
23#include "lsdb.hpp"
24#include "hello-protocol.hpp"
25#include "utility/name-helper.hpp"
akmhoque674b0b12014-05-20 14:33:28 -050026#include "logger.hpp"
akmhoque31d1d4b2014-05-05 22:08:14 -050027
28namespace nlsr {
29
akmhoque674b0b12014-05-20 14:33:28 -050030INIT_LOGGER("HelloProtocol");
31
akmhoque93f1a072014-06-19 16:24:28 -050032const std::string HelloProtocol::INFO_COMPONENT = "INFO";
33const std::string HelloProtocol::NLSR_COMPONENT = "NLSR";
akmhoque157b0a42014-05-13 00:26:37 -050034
akmhoque31d1d4b2014-05-05 22:08:14 -050035void
36HelloProtocol::expressInterest(const ndn::Name& interestName, uint32_t seconds)
37{
akmhoque674b0b12014-05-20 14:33:28 -050038 _LOG_DEBUG("Expressing Interest :" << interestName);
akmhoque31d1d4b2014-05-05 22:08:14 -050039 ndn::Interest i(interestName);
40 i.setInterestLifetime(ndn::time::seconds(seconds));
41 i.setMustBeFresh(true);
42 m_nlsr.getNlsrFace().expressInterest(i,
dmcoomes9f936662017-03-02 10:33:09 -060043 std::bind(&HelloProtocol::onContent,
akmhoque31d1d4b2014-05-05 22:08:14 -050044 this,
45 _1, _2),
Alexander Afanasyev1de901f2017-03-09 12:43:57 -080046 std::bind(&HelloProtocol::processInterestTimedOut, // Nack
47 this, _1),
dmcoomes9f936662017-03-02 10:33:09 -060048 std::bind(&HelloProtocol::processInterestTimedOut,
akmhoque31d1d4b2014-05-05 22:08:14 -050049 this, _1));
50}
51
52void
53HelloProtocol::sendScheduledInterest(uint32_t seconds)
54{
55 std::list<Adjacent> adjList = m_nlsr.getAdjacencyList().getAdjList();
56 for (std::list<Adjacent>::iterator it = adjList.begin(); it != adjList.end();
akmhoque157b0a42014-05-13 00:26:37 -050057 ++it) {
Nick G97e34942016-07-11 14:46:27 -050058 // If this adjacency has a Face, just proceed as usual.
akmhoquec04e7272014-07-02 11:00:14 -050059 if((*it).getFaceId() != 0) {
dmcoomes9f936662017-03-02 10:33:09 -060060 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoquec04e7272014-07-02 11:00:14 -050061 ndn::Name interestName = (*it).getName() ;
62 interestName.append(NLSR_COMPONENT);
63 interestName.append(INFO_COMPONENT);
64 interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
65 expressInterest(interestName,
66 m_nlsr.getConfParameter().getInterestResendTime());
dmcoomes9eaf3f42017-02-21 11:39:01 -060067 _LOG_DEBUG("Sending scheduled interest: " << interestName);
akmhoquec04e7272014-07-02 11:00:14 -050068 }
akmhoque31d1d4b2014-05-05 22:08:14 -050069 }
70 scheduleInterest(m_nlsr.getConfParameter().getInfoInterestInterval());
71}
72
73void
74HelloProtocol::scheduleInterest(uint32_t seconds)
75{
Vince Lehman50df6b72015-03-03 12:06:40 -060076 _LOG_DEBUG("Scheduling HELLO Interests in " << ndn::time::seconds(seconds));
77
Vince Lehman7c603292014-09-11 17:48:16 -050078 m_scheduler.scheduleEvent(ndn::time::seconds(seconds),
dmcoomes9f936662017-03-02 10:33:09 -060079 std::bind(&HelloProtocol::sendScheduledInterest, this, seconds));
akmhoque31d1d4b2014-05-05 22:08:14 -050080}
81
82void
83HelloProtocol::processInterest(const ndn::Name& name,
84 const ndn::Interest& interest)
85{
dmcoomes9f936662017-03-02 10:33:09 -060086 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoque31d1d4b2014-05-05 22:08:14 -050087 const ndn::Name interestName = interest.getName();
akmhoque674b0b12014-05-20 14:33:28 -050088 _LOG_DEBUG("Interest Received for Name: " << interestName);
akmhoque157b0a42014-05-13 00:26:37 -050089 if (interestName.get(-2).toUri() != INFO_COMPONENT) {
dmcoomes9eaf3f42017-02-21 11:39:01 -060090 _LOG_DEBUG("INFO_COMPONENT not found or interestName: " << interestName
91 << " does not match expression");
akmhoque31d1d4b2014-05-05 22:08:14 -050092 return;
93 }
akmhoque157b0a42014-05-13 00:26:37 -050094 ndn::Name neighbor;
95 neighbor.wireDecode(interestName.get(-1).blockFromValue());
akmhoque674b0b12014-05-20 14:33:28 -050096 _LOG_DEBUG("Neighbor: " << neighbor);
akmhoque157b0a42014-05-13 00:26:37 -050097 if (m_nlsr.getAdjacencyList().isNeighbor(neighbor)) {
dmcoomes9f936662017-03-02 10:33:09 -060098 std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
akmhoque69c9aa92014-07-23 15:15:05 -050099 data->setName(ndn::Name(interest.getName()).appendVersion());
100 data->setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
101 data->setContent(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.c_str()),
akmhoque157b0a42014-05-13 00:26:37 -0500102 INFO_COMPONENT.size());
akmhoque69c9aa92014-07-23 15:15:05 -0500103 m_nlsr.getKeyChain().sign(*data, m_nlsr.getDefaultCertName());
104 _LOG_DEBUG("Sending out data for name: " << interest.getName());
105 m_nlsr.getNlsrFace().put(*data);
Nick Gordonc780a692017-04-27 18:03:02 -0500106
107 auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
Nick G97e34942016-07-11 14:46:27 -0500108 // If this neighbor was previously inactive, send our own hello interest, too
Vince Lehmancb76ade2014-08-28 21:24:41 -0500109 if (adjacent->getStatus() == Adjacent::STATUS_INACTIVE) {
Nick G97e34942016-07-11 14:46:27 -0500110 // We can only do that if the neighbor currently has a face.
akmhoquec04e7272014-07-02 11:00:14 -0500111 if(adjacent->getFaceId() != 0){
dmcoomes9f936662017-03-02 10:33:09 -0600112 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoquec04e7272014-07-02 11:00:14 -0500113 ndn::Name interestName(neighbor);
114 interestName.append(NLSR_COMPONENT);
115 interestName.append(INFO_COMPONENT);
116 interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
117 expressInterest(interestName,
118 m_nlsr.getConfParameter().getInterestResendTime());
119 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500120 }
121 }
122}
123
124void
125HelloProtocol::processInterestTimedOut(const ndn::Interest& interest)
126{
dmcoomes9f936662017-03-02 10:33:09 -0600127 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoque31d1d4b2014-05-05 22:08:14 -0500128 const ndn::Name interestName(interest.getName());
akmhoque674b0b12014-05-20 14:33:28 -0500129 _LOG_DEBUG("Interest timed out for Name: " << interestName);
akmhoque157b0a42014-05-13 00:26:37 -0500130 if (interestName.get(-2).toUri() != INFO_COMPONENT) {
akmhoque31d1d4b2014-05-05 22:08:14 -0500131 return;
132 }
akmhoque93f1a072014-06-19 16:24:28 -0500133 ndn::Name neighbor = interestName.getPrefix(-3);
akmhoque674b0b12014-05-20 14:33:28 -0500134 _LOG_DEBUG("Neighbor: " << neighbor);
akmhoque31d1d4b2014-05-05 22:08:14 -0500135 m_nlsr.getAdjacencyList().incrementTimedOutInterestCount(neighbor);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500136
137 Adjacent::Status status = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
138
akmhoque31d1d4b2014-05-05 22:08:14 -0500139 uint32_t infoIntTimedOutCount =
140 m_nlsr.getAdjacencyList().getTimedOutInterestCount(neighbor);
akmhoque674b0b12014-05-20 14:33:28 -0500141 _LOG_DEBUG("Status: " << status);
142 _LOG_DEBUG("Info Interest Timed out: " << infoIntTimedOutCount);
akmhoque157b0a42014-05-13 00:26:37 -0500143 if ((infoIntTimedOutCount < m_nlsr.getConfParameter().getInterestRetryNumber())) {
dmcoomes9f936662017-03-02 10:33:09 -0600144 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoque31d1d4b2014-05-05 22:08:14 -0500145 ndn::Name interestName(neighbor);
akmhoque93f1a072014-06-19 16:24:28 -0500146 interestName.append(NLSR_COMPONENT);
akmhoque157b0a42014-05-13 00:26:37 -0500147 interestName.append(INFO_COMPONENT);
148 interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
dmcoomes9eaf3f42017-02-21 11:39:01 -0600149 _LOG_DEBUG("Resending interest: " << interestName);
akmhoque31d1d4b2014-05-05 22:08:14 -0500150 expressInterest(interestName,
151 m_nlsr.getConfParameter().getInterestResendTime());
152 }
Vince Lehmancb76ade2014-08-28 21:24:41 -0500153 else if ((status == Adjacent::STATUS_ACTIVE) &&
akmhoque157b0a42014-05-13 00:26:37 -0500154 (infoIntTimedOutCount == m_nlsr.getConfParameter().getInterestRetryNumber())) {
Vince Lehmancb76ade2014-08-28 21:24:41 -0500155 m_nlsr.getAdjacencyList().setStatusOfNeighbor(neighbor, Adjacent::STATUS_INACTIVE);
Vince Lehman50df6b72015-03-03 12:06:40 -0600156
dmcoomes9eaf3f42017-02-21 11:39:01 -0600157 _LOG_DEBUG("Neighbor: " << neighbor << " status changed to INACTIVE");
158
Vince Lehman50df6b72015-03-03 12:06:40 -0600159 m_nlsr.getLsdb().scheduleAdjLsaBuild();
akmhoque31d1d4b2014-05-05 22:08:14 -0500160 }
161}
162
Nick G97e34942016-07-11 14:46:27 -0500163 // This is the first function that incoming Hello data will
164 // see. This checks if the data appears to be signed, and passes it
165 // on to validate the content of the data.
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700166void
167HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
168{
akmhoquedfe615f2014-07-27 14:12:21 -0500169 _LOG_DEBUG("Received data for INFO(name): " << data.getName());
170 if (data.getSignature().hasKeyLocator()) {
171 if (data.getSignature().getKeyLocator().getType() == ndn::KeyLocator::KeyLocator_Name) {
172 _LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
173 }
174 }
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700175 m_nlsr.getValidator().validate(data,
dmcoomes9f936662017-03-02 10:33:09 -0600176 std::bind(&HelloProtocol::onContentValidated, this, _1),
177 std::bind(&HelloProtocol::onContentValidationFailed,
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700178 this, _1, _2));
179}
akmhoque31d1d4b2014-05-05 22:08:14 -0500180
Nick G97e34942016-07-11 14:46:27 -0500181 // A validator is called on the incoming data, and if the data
182 // passes the validator's description/definitions, this function is
183 // called. Set the neighbor's status to active and refresh its
184 // LSA. If there was a change in status, we schedule an adjacency
185 // LSA build.
akmhoque31d1d4b2014-05-05 22:08:14 -0500186void
dmcoomes9f936662017-03-02 10:33:09 -0600187HelloProtocol::onContentValidated(const std::shared_ptr<const ndn::Data>& data)
akmhoque31d1d4b2014-05-05 22:08:14 -0500188{
dmcoomes9f936662017-03-02 10:33:09 -0600189 // data name: /<neighbor>/NLSR/INFO/<router>/<version>
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700190 ndn::Name dataName = data->getName();
akmhoquedfe615f2014-07-27 14:12:21 -0500191 _LOG_DEBUG("Data validation successful for INFO(name): " << dataName);
akmhoque157b0a42014-05-13 00:26:37 -0500192 if (dataName.get(-3).toUri() == INFO_COMPONENT) {
akmhoque93f1a072014-06-19 16:24:28 -0500193 ndn::Name neighbor = dataName.getPrefix(-4);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500194
195 Adjacent::Status oldStatus = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
196 m_nlsr.getAdjacencyList().setStatusOfNeighbor(neighbor, Adjacent::STATUS_ACTIVE);
akmhoque31d1d4b2014-05-05 22:08:14 -0500197 m_nlsr.getAdjacencyList().setTimedOutInterestCount(neighbor, 0);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500198 Adjacent::Status newStatus = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
199
akmhoque2f423352014-06-03 11:49:35 -0500200 _LOG_DEBUG("Neighbor : " << neighbor);
akmhoque674b0b12014-05-20 14:33:28 -0500201 _LOG_DEBUG("Old Status: " << oldStatus << " New Status: " << newStatus);
akmhoque157b0a42014-05-13 00:26:37 -0500202 // change in Adjacency list
203 if ((oldStatus - newStatus) != 0) {
Ashlesh Gawandec5fa3202016-12-05 13:21:51 -0600204 if (m_nlsr.getConfParameter().getHyperbolicState() == HYPERBOLIC_STATE_ON) {
205 m_nlsr.getRoutingTable().scheduleRoutingTableCalculation(m_nlsr);
206 }
207 else {
208 m_nlsr.getLsdb().scheduleAdjLsaBuild();
209 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500210 }
211 }
212}
213
Nick G97e34942016-07-11 14:46:27 -0500214 // Simply logs a debug message that the content could not be
215 // validated (and is implicitly being discarded as a result).
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700216void
dmcoomes9f936662017-03-02 10:33:09 -0600217HelloProtocol::onContentValidationFailed(const std::shared_ptr<const ndn::Data>& data,
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700218 const std::string& msg)
219{
220 _LOG_DEBUG("Validation Error: " << msg);
221}
222
Nick Gordonfad8e252016-08-11 14:21:38 -0500223} // namespace nlsr