blob: 75e6bae59d3eefe2a5a858ab44ac51577eb64907 [file] [log] [blame]
alvy297f4162015-03-03 17:15:33 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, The University of Memphis,
4 * Regents of the University of California,
5 * Arizona Board of Regents.
6 *
7 * This file is part of NLSR (Named-data Link State Routing).
8 * See AUTHORS.md for complete list of NLSR authors and contributors.
9 *
10 * NLSR is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20 **/
21
22#include "prefix-update-processor.hpp"
23
24#include "lsdb.hpp"
25#include "nlsr.hpp"
26#include "prefix-update-commands.hpp"
27#include "communication/sync-logic-handler.hpp"
28
29#include <ndn-cxx/management/nfd-control-response.hpp>
30
31namespace nlsr {
32namespace update {
33
34INIT_LOGGER("PrefixUpdateProcessor");
35
36const ndn::Name::Component PrefixUpdateProcessor::MODULE_COMPONENT = ndn::Name::Component("prefix-update");
37const ndn::Name::Component PrefixUpdateProcessor::ADVERTISE_VERB = ndn::Name::Component("advertise");
38const ndn::Name::Component PrefixUpdateProcessor::WITHDRAW_VERB = ndn::Name::Component("withdraw");
39
40PrefixUpdateProcessor::PrefixUpdateProcessor(ndn::Face& face,
41 NamePrefixList& namePrefixList,
42 Lsdb& lsdb,
43 SyncLogicHandler& sync,
44 const ndn::Name broadcastPrefix,
45 ndn::KeyChain& keyChain,
46 ndn::shared_ptr<ndn::CertificateCacheTtl> certificateCache)
47 : m_face(face)
48 , m_namePrefixList(namePrefixList)
49 , m_lsdb(lsdb)
50 , m_sync(sync)
51 , m_keyChain(keyChain)
52 , m_validator(m_face, broadcastPrefix, certificateCache)
53 , COMMAND_PREFIX(ndn::Name(Nlsr::LOCALHOST_PREFIX).append(MODULE_COMPONENT))
54{
55}
56
57void
58PrefixUpdateProcessor::startListening()
59{
60 _LOG_DEBUG("Setting Interest filter for: " << COMMAND_PREFIX);
61
62 m_face.setInterestFilter(COMMAND_PREFIX, bind(&PrefixUpdateProcessor::onInterest, this, _2));
63}
64
65void
66PrefixUpdateProcessor::onInterest(const ndn::Interest& request)
67{
68 _LOG_TRACE("Received Interest: " << request);
69
70 m_validator.validate(request,
71 bind(&PrefixUpdateProcessor::onCommandValidated, this, _1),
72 bind(&PrefixUpdateProcessor::onCommandValidationFailed, this, _1, _2));
73}
74
75void
76PrefixUpdateProcessor::loadValidator(boost::property_tree::ptree section,
77 const std::string& filename)
78{
79 m_validator.load(section, filename);
80}
81
82void
83PrefixUpdateProcessor::onCommandValidated(const std::shared_ptr<const ndn::Interest>& request)
84{
85 const ndn::Name& command = request->getName();
86 const ndn::Name::Component& verb = command[COMMAND_PREFIX.size()];
87 const ndn::Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
88
89 if (verb == ADVERTISE_VERB || verb == WITHDRAW_VERB) {
90 ndn::nfd::ControlParameters parameters;
91
92 if (!extractParameters(parameterComponent, parameters)) {
93 sendResponse(request, 400, "Malformed command");
94 return;
95 }
96
97 if (verb == ADVERTISE_VERB) {
98 advertise(request, parameters);
99 }
100 else if (verb == WITHDRAW_VERB) {
101 withdraw(request, parameters);
102 }
103
104 sendResponse(request, 200, "Success");
105 }
106 else {
107 sendResponse(request, 501, "Unsupported command");
108 }
109}
110
111void
112PrefixUpdateProcessor::onCommandValidationFailed(const std::shared_ptr<const ndn::Interest>& request,
113 const std::string& failureInfo)
114{
115 sendResponse(request, 403, failureInfo);
116}
117
118bool
119PrefixUpdateProcessor::extractParameters(const ndn::Name::Component& parameterComponent,
120 ndn::nfd::ControlParameters& extractedParameters)
121{
122 try {
123 ndn::Block rawParameters = parameterComponent.blockFromValue();
124 extractedParameters.wireDecode(rawParameters);
125 }
126 catch (const ndn::tlv::Error&) {
127 return false;
128 }
129
130 return true;
131}
132
133void
134PrefixUpdateProcessor::advertise(const std::shared_ptr<const ndn::Interest>& request,
135 const ndn::nfd::ControlParameters& parameters)
136{
137 AdvertisePrefixCommand command;
138
139 if (!validateParameters(command, parameters)) {
140 sendResponse(request, 400, "Malformed command");
141 return;
142 }
143
144 _LOG_INFO("Advertising name: " << parameters.getName());
145
146 if (m_namePrefixList.insert(parameters.getName())) {
147 // Only build a Name LSA if the added name is new
148 m_lsdb.buildAndInstallOwnNameLsa();
149 m_sync.publishRoutingUpdate();
150 }
151}
152
153void
154PrefixUpdateProcessor::withdraw(const std::shared_ptr<const ndn::Interest>& request,
155 const ndn::nfd::ControlParameters& parameters)
156{
157 WithdrawPrefixCommand command;
158
159 if (!validateParameters(command, parameters)) {
160 sendResponse(request, 400, "Malformed command");
161 return;
162 }
163
164 _LOG_INFO("Withdrawing name: " << parameters.getName());
165
166 if (m_namePrefixList.remove(parameters.getName())) {
167 // Only build a Name LSA if a name was actually removed
168 m_lsdb.buildAndInstallOwnNameLsa();
169 m_sync.publishRoutingUpdate();
170 }
171}
172
173bool
174PrefixUpdateProcessor::validateParameters(const ndn::nfd::ControlCommand& command,
175 const ndn::nfd::ControlParameters& parameters)
176{
177 try {
178 command.validateRequest(parameters);
179 }
180 catch (const ndn::nfd::ControlCommand::ArgumentError&) {
181 return false;
182 }
183
184 return true;
185}
186
187void
188PrefixUpdateProcessor::sendResponse(const std::shared_ptr<const ndn::Interest>& request,
189 uint32_t code,
190 const std::string& text)
191{
192 if (request == nullptr) {
193 return;
194 }
195
196 ndn::nfd::ControlResponse response(code, text);
197 const ndn::Block& encodedControl = response.wireEncode();
198
199 std::shared_ptr<ndn::Data> responseData = ndn::make_shared<ndn::Data>(request->getName());
200 responseData->setContent(encodedControl);
201
202 m_keyChain.sign(*responseData);
203 m_face.put(*responseData);
204}
205
206} // namespace update
207} // namespace nlsr