blob: bad22654252dd0bcf5b12c5a1fe220e29719bc2c [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;
Obaidea56c612014-03-17 22:50:47 -050041 m_face.shutdown();
Obaid3f48fe52014-02-27 21:45:23 -060042}
43
44Nrd::Nrd()
45 : m_nfdController(new nfd::Controller(m_face)),
46 m_verbDispatch(COMMAND_VERBS,
47 COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
48{
Obaidea56c612014-03-17 22:50:47 -050049 //check whether the components of localhop and localhost prefixes are same
Alexander Afanasyev80f06a52014-03-27 14:40:00 -070050 BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
Obaidea56c612014-03-17 22:50:47 -050051
52 std::cerr << "Setting interest filter on: " << COMMAND_PREFIX.toUri() << std::endl;
Obaid3f48fe52014-02-27 21:45:23 -060053 m_face.setController(m_nfdController);
Obaidea56c612014-03-17 22:50:47 -050054 m_face.setInterestFilter(COMMAND_PREFIX.toUri(),
Obaid3f48fe52014-02-27 21:45:23 -060055 bind(&Nrd::onRibRequest, this, _2),
Obaidea56c612014-03-17 22:50:47 -050056 bind(&Nrd::setInterestFilterFailed, this, _1, _2));
Alexander Afanasyev80f06a52014-03-27 14:40:00 -070057
Obaidea56c612014-03-17 22:50:47 -050058 std::cerr << "Setting interest filter on: " << REMOTE_COMMAND_PREFIX.toUri() << std::endl;
59 m_face.setInterestFilter(REMOTE_COMMAND_PREFIX.toUri(),
60 bind(&Nrd::onRibRequest, this, _2),
61 bind(&Nrd::setInterestFilterFailed, this, _1, _2));
Obaid3f48fe52014-02-27 21:45:23 -060062}
63
64void
65Nrd::sendResponse(const Name& name,
66 const nfd::ControlResponse& response)
67{
68 const Block& encodedControl = response.wireEncode();
69
70 Data responseData(name);
71 responseData.setContent(encodedControl);
72
73 m_keyChain.sign(responseData);
74 m_face.put(responseData);
75}
76
77void
78Nrd::sendResponse(const Name& name,
79 uint32_t code,
80 const std::string& text)
81{
82 nfd::ControlResponse response(code, text);
83 sendResponse(name, response);
84}
85
86void
87Nrd::onRibRequest(const Interest& request)
88{
89 const Name& command = request.getName();
90 const size_t commandNComps = command.size();
91
92 if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
93 commandNComps < COMMAND_SIGNED_NCOMPS)
94 {
95 std::cerr << "Error: Signature required" << std::endl;
96 sendResponse(command, 401, "Signature required");
97 return;
98 }
99 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
Obaidea56c612014-03-17 22:50:47 -0500100 !(COMMAND_PREFIX.isPrefixOf(command) ||
101 REMOTE_COMMAND_PREFIX.isPrefixOf(command)))
102 {
Obaid3f48fe52014-02-27 21:45:23 -0600103 std::cerr << "Error: Malformed Command" << std::endl;
104 sendResponse(command, 400, "Malformed command");
105 return;
106 }
107
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700108 //REMOTE_COMMAND_PREFIX number of componenets are same as
Obaidea56c612014-03-17 22:50:47 -0500109 // NRD_COMMAND_PREFIX's so no extra checks are required.
Obaid3f48fe52014-02-27 21:45:23 -0600110 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
111 VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
112
113 if (verbProcessor != m_verbDispatch.end())
114 {
115 PrefixRegOptions options;
116 if (!extractOptions(request, options))
117 {
118 sendResponse(command, 400, "Malformed command");
119 return;
120 }
121
122 /// \todo authorize command
123 if (false)
124 {
125 sendResponse(request.getName(), 403, "Unauthorized command");
126 return;
127 }
128
129 // \todo add proper log support
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700130 std::cout << "Received options (name, faceid, cost): " << options.getName() <<
Obaid3f48fe52014-02-27 21:45:23 -0600131 ", " << options.getFaceId() << ", " << options.getCost() << std::endl;
132
133 nfd::ControlResponse response;
134 (verbProcessor->second)(this, request, options);
135 }
136 else
137 {
138 sendResponse(request.getName(), 501, "Unsupported command");
139 }
140}
141
142bool
143Nrd::extractOptions(const Interest& request,
144 PrefixRegOptions& extractedOptions)
145{
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700146 // const Name& command = request.getName();
147 //REMOTE_COMMAND_PREFIX is same in size of NRD_COMMAND_PREFIX
Obaidea56c612014-03-17 22:50:47 -0500148 //so no extra processing is required.
Obaid3f48fe52014-02-27 21:45:23 -0600149 const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
150
151 try
152 {
153 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
154 extractedOptions.wireDecode(rawOptions);
155 }
156 catch (const ndn::Tlv::Error& e)
157 {
158 return false;
159 }
160
161 if (extractedOptions.getFaceId() == 0)
162 {
163 std::cout <<"IncomingFaceId: " << request.getIncomingFaceId() << std::endl;
164 extractedOptions.setFaceId(request.getIncomingFaceId());
165 }
166 return true;
167}
168
169void
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700170Nrd::onCommandError(const std::string& error,
171 const Interest& request,
Obaid3f48fe52014-02-27 21:45:23 -0600172 const PrefixRegOptions& options)
173{
174 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700175
Obaid3f48fe52014-02-27 21:45:23 -0600176 response.setCode(400);
177 response.setText(error);
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700178
Obaid3f48fe52014-02-27 21:45:23 -0600179 std::cout << "Error: " << error << std::endl;
180 sendResponse(request.getName(), response);
181 m_managedRib.erase(options);
182}
183
184void
185Nrd::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
186{
187 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700188
Obaid3f48fe52014-02-27 21:45:23 -0600189 response.setCode(200);
190 response.setText("Success");
191 response.setBody(options.wireEncode());
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700192
193 std::cout << "Success: Name unregistered (" <<
194 options.getName() << ", " <<
Obaid3f48fe52014-02-27 21:45:23 -0600195 options.getFaceId() << ")" << std::endl;
196 sendResponse(request.getName(), response);
197 m_managedRib.erase(options);
198}
199
200void
201Nrd::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
202{
203 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700204
Obaid3f48fe52014-02-27 21:45:23 -0600205 response.setCode(200);
206 response.setText("Success");
207 response.setBody(options.wireEncode());
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700208
209 std::cout << "Success: Name registered (" << options.getName() << ", " <<
Obaid3f48fe52014-02-27 21:45:23 -0600210 options.getFaceId() << ")" << std::endl;
211 sendResponse(request.getName(), response);
212}
213
214
215void
216Nrd::insertEntry(const Interest& request, const PrefixRegOptions& options)
217{
218 // For right now, just pass the options to fib as it is,
219 // without processing flags. Later options will be first added to
220 // Rib tree, then nrd will generate fib updates based on flags and then
221 // will add next hops one by one..
222 m_managedRib.insert(options);
223 m_nfdController->fibAddNextHop(options.getName(), options.getFaceId(),
224 options.getCost(),
225 bind(&Nrd::onRegSuccess, this, request, options),
226 bind(&Nrd::onCommandError, this, _1, request, options));
227}
228
229
230void
231Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
232{
233 m_nfdController->fibRemoveNextHop(options.getName(),
234 options.getFaceId(),
235 bind(&Nrd::onUnRegSuccess, this, request, options),
236 bind(&Nrd::onCommandError, this, _1, request, options));
237}
238
239
240void
241Nrd::listen()
242{
243 std::cout << "NRD started: listening for incoming interests" << std::endl;
244 m_face.processEvents();
245}
246
247
248void
249Nrd::onControlHeaderSuccess()
250{
251 std::cout << "Local control header enabled" << std::endl;
252}
253
254
255void
256Nrd::onControlHeaderError()
257{
258 std::cout << "Error: couldn't enable local control header" << std::endl;
259 m_face.shutdown();
260}
261
262
263void
264Nrd::enableLocalControlHeader()
265{
266 Name enable("/localhost/nfd/control-header/in-faceid/enable");
267 Interest enableCommand(enable);
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700268
Obaid3f48fe52014-02-27 21:45:23 -0600269 m_keyChain.sign(enableCommand);
270 m_face.expressInterest(enableCommand,
271 ndn::bind(&Nrd::onControlHeaderSuccess, this),
272 ndn::bind(&Nrd::onControlHeaderError, this));
273}
274
275} // namespace nrd
276} // namespace ndn