blob: f22c0000ce53cd4507997ef2488f43135518dc5a [file] [log] [blame]
Obaid3f48fe52014-02-27 21:45:23 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "nrd.hpp"
8
9namespace ndn {
10namespace nrd {
11
12const Name Nrd::COMMAND_PREFIX = "/localhost/nrd";
Obaidea56c612014-03-17 22:50:47 -050013const Name Nrd::REMOTE_COMMAND_PREFIX = "/localhop/nrd";
Obaid3f48fe52014-02-27 21:45:23 -060014
15const size_t Nrd::COMMAND_UNSIGNED_NCOMPS =
16 Nrd::COMMAND_PREFIX.size() +
17 1 + // verb
18 1; // verb options
19
20const size_t Nrd::COMMAND_SIGNED_NCOMPS =
21 Nrd::COMMAND_UNSIGNED_NCOMPS +
22 4; // (timestamp, nonce, signed info tlv, signature tlv)
23
24const Nrd::VerbAndProcessor Nrd::COMMAND_VERBS[] =
25 {
26 VerbAndProcessor(
27 Name::Component("register"),
28 &Nrd::insertEntry
29 ),
30
31 VerbAndProcessor(
32 Name::Component("unregister"),
33 &Nrd::deleteEntry
34 ),
35 };
36
37void
Alexander Afanasyev80f06a52014-03-27 14:40:00 -070038Nrd::setInterestFilterFailed(const Name& name, const std::string& msg)
Obaid3f48fe52014-02-27 21:45:23 -060039{
40 std::cerr << "Error in setting interest filter (" << name << "): " << msg << std::endl;
Yingdi Yudefb5e42014-03-31 18:18:09 -070041 m_face->shutdown();
Obaid3f48fe52014-02-27 21:45:23 -060042}
43
Yingdi Yudefb5e42014-03-31 18:18:09 -070044Nrd::Nrd(const std::string& validatorConfig)
45 : m_face(new Face())
46 , m_validator(m_face)
47 , m_nfdController(new nfd::Controller(*m_face))
Alexander Afanasyevd9e98732014-03-27 16:09:10 -070048 , m_verbDispatch(COMMAND_VERBS,
Obaid3f48fe52014-02-27 21:45:23 -060049 COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
50{
Obaidea56c612014-03-17 22:50:47 -050051 //check whether the components of localhop and localhost prefixes are same
Alexander Afanasyev80f06a52014-03-27 14:40:00 -070052 BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
Obaidea56c612014-03-17 22:50:47 -050053
Yingdi Yudefb5e42014-03-31 18:18:09 -070054 m_validator.load(validatorConfig);
55
Obaidea56c612014-03-17 22:50:47 -050056 std::cerr << "Setting interest filter on: " << COMMAND_PREFIX.toUri() << std::endl;
Yingdi Yudefb5e42014-03-31 18:18:09 -070057 m_face->setController(m_nfdController);
58 m_face->setInterestFilter(COMMAND_PREFIX.toUri(),
59 bind(&Nrd::onRibRequest, this, _2),
60 bind(&Nrd::setInterestFilterFailed, this, _1, _2));
Alexander Afanasyev80f06a52014-03-27 14:40:00 -070061
Obaidea56c612014-03-17 22:50:47 -050062 std::cerr << "Setting interest filter on: " << REMOTE_COMMAND_PREFIX.toUri() << std::endl;
Yingdi Yudefb5e42014-03-31 18:18:09 -070063 m_face->setInterestFilter(REMOTE_COMMAND_PREFIX.toUri(),
64 bind(&Nrd::onRibRequest, this, _2),
65 bind(&Nrd::setInterestFilterFailed, this, _1, _2));
Obaid3f48fe52014-02-27 21:45:23 -060066}
67
68void
69Nrd::sendResponse(const Name& name,
70 const nfd::ControlResponse& response)
71{
72 const Block& encodedControl = response.wireEncode();
73
74 Data responseData(name);
75 responseData.setContent(encodedControl);
76
77 m_keyChain.sign(responseData);
Yingdi Yudefb5e42014-03-31 18:18:09 -070078 m_face->put(responseData);
Obaid3f48fe52014-02-27 21:45:23 -060079}
80
81void
82Nrd::sendResponse(const Name& name,
83 uint32_t code,
84 const std::string& text)
85{
86 nfd::ControlResponse response(code, text);
87 sendResponse(name, response);
88}
89
90void
91Nrd::onRibRequest(const Interest& request)
92{
Yingdi Yudefb5e42014-03-31 18:18:09 -070093 m_validator.validate(request,
94 bind(&Nrd::onRibRequestValidated, this, _1),
95 bind(&Nrd::onRibRequestValidationFailed, this, _1, _2));
96}
Obaid3f48fe52014-02-27 21:45:23 -060097
Yingdi Yudefb5e42014-03-31 18:18:09 -070098void
99Nrd::onRibRequestValidated(const shared_ptr<const Interest>& request)
100{
101 const Name& command = request->getName();
Obaid3f48fe52014-02-27 21:45:23 -0600102
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700103 //REMOTE_COMMAND_PREFIX number of componenets are same as
Obaidea56c612014-03-17 22:50:47 -0500104 // NRD_COMMAND_PREFIX's so no extra checks are required.
Obaid3f48fe52014-02-27 21:45:23 -0600105 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
106 VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
107
108 if (verbProcessor != m_verbDispatch.end())
109 {
110 PrefixRegOptions options;
Yingdi Yudefb5e42014-03-31 18:18:09 -0700111 if (!extractOptions(*request, options))
Obaid3f48fe52014-02-27 21:45:23 -0600112 {
113 sendResponse(command, 400, "Malformed command");
114 return;
115 }
116
117 /// \todo authorize command
118 if (false)
119 {
Yingdi Yudefb5e42014-03-31 18:18:09 -0700120 sendResponse(request->getName(), 403, "Unauthorized command");
Obaid3f48fe52014-02-27 21:45:23 -0600121 return;
122 }
123
124 // \todo add proper log support
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700125 std::cout << "Received options (name, faceid, cost): " << options.getName() <<
Yingdi Yudefb5e42014-03-31 18:18:09 -0700126 ", " << options.getFaceId() << ", " << options.getCost() << std::endl;
Obaid3f48fe52014-02-27 21:45:23 -0600127
128 nfd::ControlResponse response;
Yingdi Yudefb5e42014-03-31 18:18:09 -0700129 (verbProcessor->second)(this, *request, options);
Obaid3f48fe52014-02-27 21:45:23 -0600130 }
131 else
132 {
Yingdi Yudefb5e42014-03-31 18:18:09 -0700133 sendResponse(request->getName(), 501, "Unsupported command");
Obaid3f48fe52014-02-27 21:45:23 -0600134 }
135}
136
Yingdi Yudefb5e42014-03-31 18:18:09 -0700137void
138Nrd::onRibRequestValidationFailed(const shared_ptr<const Interest>& request,
139 const std::string& failureInfo)
140{
141 sendResponse(request->getName(), 403, failureInfo);
142}
143
Obaid3f48fe52014-02-27 21:45:23 -0600144bool
145Nrd::extractOptions(const Interest& request,
146 PrefixRegOptions& extractedOptions)
147{
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700148 // const Name& command = request.getName();
149 //REMOTE_COMMAND_PREFIX is same in size of NRD_COMMAND_PREFIX
Obaidea56c612014-03-17 22:50:47 -0500150 //so no extra processing is required.
Obaid3f48fe52014-02-27 21:45:23 -0600151 const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
152
153 try
154 {
155 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
156 extractedOptions.wireDecode(rawOptions);
157 }
158 catch (const ndn::Tlv::Error& e)
159 {
160 return false;
161 }
162
163 if (extractedOptions.getFaceId() == 0)
164 {
165 std::cout <<"IncomingFaceId: " << request.getIncomingFaceId() << std::endl;
166 extractedOptions.setFaceId(request.getIncomingFaceId());
167 }
168 return true;
169}
170
171void
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700172Nrd::onCommandError(uint32_t code, const std::string& error,
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700173 const Interest& request,
Obaid3f48fe52014-02-27 21:45:23 -0600174 const PrefixRegOptions& options)
175{
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700176 std::cout << "NFD Error: " << error << " (code: " << code << ")" << std::endl;
177
Obaid3f48fe52014-02-27 21:45:23 -0600178 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700179
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700180 if (code == 404)
181 {
182 response.setCode(code);
183 response.setText(error);
184 }
185 else
186 {
187 response.setCode(533);
188 std::ostringstream os;
189 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
190 response.setText(os.str());
191 }
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700192
Obaid3f48fe52014-02-27 21:45:23 -0600193 sendResponse(request.getName(), response);
194 m_managedRib.erase(options);
195}
196
197void
198Nrd::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
199{
200 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700201
Obaid3f48fe52014-02-27 21:45:23 -0600202 response.setCode(200);
203 response.setText("Success");
204 response.setBody(options.wireEncode());
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700205
206 std::cout << "Success: Name unregistered (" <<
Yingdi Yudefb5e42014-03-31 18:18:09 -0700207 options.getName() << ", " <<
208 options.getFaceId() << ")" << std::endl;
Obaid3f48fe52014-02-27 21:45:23 -0600209 sendResponse(request.getName(), response);
210 m_managedRib.erase(options);
211}
212
213void
214Nrd::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
215{
216 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700217
Obaid3f48fe52014-02-27 21:45:23 -0600218 response.setCode(200);
219 response.setText("Success");
220 response.setBody(options.wireEncode());
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700221
222 std::cout << "Success: Name registered (" << options.getName() << ", " <<
Yingdi Yudefb5e42014-03-31 18:18:09 -0700223 options.getFaceId() << ")" << std::endl;
Obaid3f48fe52014-02-27 21:45:23 -0600224 sendResponse(request.getName(), response);
225}
226
227
228void
229Nrd::insertEntry(const Interest& request, const PrefixRegOptions& options)
230{
231 // For right now, just pass the options to fib as it is,
232 // without processing flags. Later options will be first added to
233 // Rib tree, then nrd will generate fib updates based on flags and then
234 // will add next hops one by one..
235 m_managedRib.insert(options);
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700236 m_nfdController->start<nfd::FibAddNextHopCommand>(
Yingdi Yudefb5e42014-03-31 18:18:09 -0700237 nfd::ControlParameters()
238 .setName(options.getName())
239 .setFaceId(options.getFaceId())
240 .setCost(options.getCost()),
241 bind(&Nrd::onRegSuccess, this, request, options),
242 bind(&Nrd::onCommandError, this, _1, _2, request, options));
Obaid3f48fe52014-02-27 21:45:23 -0600243}
244
245
246void
247Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
248{
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700249 m_nfdController->start<nfd::FibRemoveNextHopCommand>(
Yingdi Yudefb5e42014-03-31 18:18:09 -0700250 nfd::ControlParameters()
251 .setName(options.getName())
252 .setFaceId(options.getFaceId()),
253 bind(&Nrd::onUnRegSuccess, this, request, options),
254 bind(&Nrd::onCommandError, this, _1, _2, request, options));
Obaid3f48fe52014-02-27 21:45:23 -0600255}
256
257
258void
259Nrd::listen()
260{
261 std::cout << "NRD started: listening for incoming interests" << std::endl;
Yingdi Yudefb5e42014-03-31 18:18:09 -0700262 m_face->processEvents();
Obaid3f48fe52014-02-27 21:45:23 -0600263}
264
265
266void
267Nrd::onControlHeaderSuccess()
268{
269 std::cout << "Local control header enabled" << std::endl;
270}
271
272
273void
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700274Nrd::onControlHeaderError(uint32_t code, const std::string& reason)
Obaid3f48fe52014-02-27 21:45:23 -0600275{
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700276 std::cout << "Error: couldn't enable local control header "
277 << "(code: " << code << ", info: " << reason << ")" << std::endl;
Yingdi Yudefb5e42014-03-31 18:18:09 -0700278 m_face->shutdown();
Obaid3f48fe52014-02-27 21:45:23 -0600279}
280
281
282void
283Nrd::enableLocalControlHeader()
284{
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700285 m_nfdController->start<nfd::FaceEnableLocalControlCommand>(
286 nfd::ControlParameters()
287 .setLocalControlFeature(nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
288 bind(&Nrd::onControlHeaderSuccess, this),
Yingdi Yudefb5e42014-03-31 18:18:09 -0700289 bind(&Nrd::onControlHeaderError, this, _1, _2));
Obaid3f48fe52014-02-27 21:45:23 -0600290}
291
292} // namespace nrd
293} // namespace ndn