blob: 403a32fe5d0ad501ef71ac336297b3fcd198fba3 [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()
Alexander Afanasyevd9e98732014-03-27 16:09:10 -070045 : m_nfdController(new nfd::Controller(m_face))
46 , m_verbDispatch(COMMAND_VERBS,
Obaid3f48fe52014-02-27 21:45:23 -060047 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 Afanasyevd9e98732014-03-27 16:09:10 -0700170Nrd::onCommandError(uint32_t code, const std::string& error,
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700171 const Interest& request,
Obaid3f48fe52014-02-27 21:45:23 -0600172 const PrefixRegOptions& options)
173{
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700174 std::cout << "NFD Error: " << error << " (code: " << code << ")" << std::endl;
175
Obaid3f48fe52014-02-27 21:45:23 -0600176 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700177
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700178 if (code == 404)
179 {
180 response.setCode(code);
181 response.setText(error);
182 }
183 else
184 {
185 response.setCode(533);
186 std::ostringstream os;
187 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
188 response.setText(os.str());
189 }
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700190
Obaid3f48fe52014-02-27 21:45:23 -0600191 sendResponse(request.getName(), response);
192 m_managedRib.erase(options);
193}
194
195void
196Nrd::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
197{
198 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700199
Obaid3f48fe52014-02-27 21:45:23 -0600200 response.setCode(200);
201 response.setText("Success");
202 response.setBody(options.wireEncode());
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700203
204 std::cout << "Success: Name unregistered (" <<
205 options.getName() << ", " <<
Obaid3f48fe52014-02-27 21:45:23 -0600206 options.getFaceId() << ")" << std::endl;
207 sendResponse(request.getName(), response);
208 m_managedRib.erase(options);
209}
210
211void
212Nrd::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
213{
214 nfd::ControlResponse response;
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700215
Obaid3f48fe52014-02-27 21:45:23 -0600216 response.setCode(200);
217 response.setText("Success");
218 response.setBody(options.wireEncode());
Alexander Afanasyev80f06a52014-03-27 14:40:00 -0700219
220 std::cout << "Success: Name registered (" << options.getName() << ", " <<
Obaid3f48fe52014-02-27 21:45:23 -0600221 options.getFaceId() << ")" << std::endl;
222 sendResponse(request.getName(), response);
223}
224
225
226void
227Nrd::insertEntry(const Interest& request, const PrefixRegOptions& options)
228{
229 // For right now, just pass the options to fib as it is,
230 // without processing flags. Later options will be first added to
231 // Rib tree, then nrd will generate fib updates based on flags and then
232 // will add next hops one by one..
233 m_managedRib.insert(options);
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700234 m_nfdController->start<nfd::FibAddNextHopCommand>(
235 nfd::ControlParameters()
236 .setName(options.getName())
237 .setFaceId(options.getFaceId())
238 .setCost(options.getCost()),
239 bind(&Nrd::onRegSuccess, this, request, options),
240 bind(&Nrd::onCommandError, this, _1, _2, request, options)
241 );
Obaid3f48fe52014-02-27 21:45:23 -0600242}
243
244
245void
246Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
247{
Alexander Afanasyevd9e98732014-03-27 16:09:10 -0700248 m_nfdController->start<nfd::FibRemoveNextHopCommand>(
249 nfd::ControlParameters()
250 .setName(options.getName())
251 .setFaceId(options.getFaceId()),
252 bind(&Nrd::onUnRegSuccess, this, request, options),
253 bind(&Nrd::onCommandError, this, _1, _2, request, options)
254 );
Obaid3f48fe52014-02-27 21:45:23 -0600255}
256
257
258void
259Nrd::listen()
260{
261 std::cout << "NRD started: listening for incoming interests" << std::endl;
262 m_face.processEvents();
263}
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;
Obaid3f48fe52014-02-27 21:45:23 -0600278 m_face.shutdown();
279}
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),
289 bind(&Nrd::onControlHeaderError, this, _1, _2)
290 );
Obaid3f48fe52014-02-27 21:45:23 -0600291}
292
293} // namespace nrd
294} // namespace ndn