blob: 0928a63002179c2343b63fe29ab31423cacea0c9 [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";
13
14const size_t Nrd::COMMAND_UNSIGNED_NCOMPS =
15 Nrd::COMMAND_PREFIX.size() +
16 1 + // verb
17 1; // verb options
18
19const size_t Nrd::COMMAND_SIGNED_NCOMPS =
20 Nrd::COMMAND_UNSIGNED_NCOMPS +
21 4; // (timestamp, nonce, signed info tlv, signature tlv)
22
23const Nrd::VerbAndProcessor Nrd::COMMAND_VERBS[] =
24 {
25 VerbAndProcessor(
26 Name::Component("register"),
27 &Nrd::insertEntry
28 ),
29
30 VerbAndProcessor(
31 Name::Component("unregister"),
32 &Nrd::deleteEntry
33 ),
34 };
35
36void
37setInterestFilterFailed(const Name& name, const std::string& msg)
38{
39 std::cerr << "Error in setting interest filter (" << name << "): " << msg << std::endl;
40}
41
42Nrd::Nrd()
43 : m_nfdController(new nfd::Controller(m_face)),
44 m_verbDispatch(COMMAND_VERBS,
45 COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
46{
47 m_face.setController(m_nfdController);
48 m_face.setInterestFilter("/localhost/nrd",
49 bind(&Nrd::onRibRequest, this, _2),
50 bind(&setInterestFilterFailed, _1, _2));
51}
52
53void
54Nrd::sendResponse(const Name& name,
55 const nfd::ControlResponse& response)
56{
57 const Block& encodedControl = response.wireEncode();
58
59 Data responseData(name);
60 responseData.setContent(encodedControl);
61
62 m_keyChain.sign(responseData);
63 m_face.put(responseData);
64}
65
66void
67Nrd::sendResponse(const Name& name,
68 uint32_t code,
69 const std::string& text)
70{
71 nfd::ControlResponse response(code, text);
72 sendResponse(name, response);
73}
74
75void
76Nrd::onRibRequest(const Interest& request)
77{
78 const Name& command = request.getName();
79 const size_t commandNComps = command.size();
80
81 if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
82 commandNComps < COMMAND_SIGNED_NCOMPS)
83 {
84 std::cerr << "Error: Signature required" << std::endl;
85 sendResponse(command, 401, "Signature required");
86 return;
87 }
88 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
89 !COMMAND_PREFIX.isPrefixOf(command))
90 {
91 std::cerr << "Error: Malformed Command" << std::endl;
92 sendResponse(command, 400, "Malformed command");
93 return;
94 }
95
96 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
97 VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
98
99 if (verbProcessor != m_verbDispatch.end())
100 {
101 PrefixRegOptions options;
102 if (!extractOptions(request, options))
103 {
104 sendResponse(command, 400, "Malformed command");
105 return;
106 }
107
108 /// \todo authorize command
109 if (false)
110 {
111 sendResponse(request.getName(), 403, "Unauthorized command");
112 return;
113 }
114
115 // \todo add proper log support
116 std::cout << "Received options (name, faceid, cost): " << options.getName() <<
117 ", " << options.getFaceId() << ", " << options.getCost() << std::endl;
118
119 nfd::ControlResponse response;
120 (verbProcessor->second)(this, request, options);
121 }
122 else
123 {
124 sendResponse(request.getName(), 501, "Unsupported command");
125 }
126}
127
128bool
129Nrd::extractOptions(const Interest& request,
130 PrefixRegOptions& extractedOptions)
131{
132 const Name& command = request.getName();
133 const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
134
135 try
136 {
137 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
138 extractedOptions.wireDecode(rawOptions);
139 }
140 catch (const ndn::Tlv::Error& e)
141 {
142 return false;
143 }
144
145 if (extractedOptions.getFaceId() == 0)
146 {
147 std::cout <<"IncomingFaceId: " << request.getIncomingFaceId() << std::endl;
148 extractedOptions.setFaceId(request.getIncomingFaceId());
149 }
150 return true;
151}
152
153void
154Nrd::onCommandError(const std::string& error,
155 const Interest& request,
156 const PrefixRegOptions& options)
157{
158 nfd::ControlResponse response;
159
160 response.setCode(400);
161 response.setText(error);
162
163 std::cout << "Error: " << error << std::endl;
164 sendResponse(request.getName(), response);
165 m_managedRib.erase(options);
166}
167
168void
169Nrd::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
170{
171 nfd::ControlResponse response;
172
173 response.setCode(200);
174 response.setText("Success");
175 response.setBody(options.wireEncode());
176
177 std::cout << "Success: Name unregistered (" <<
178 options.getName() << ", " <<
179 options.getFaceId() << ")" << std::endl;
180 sendResponse(request.getName(), response);
181 m_managedRib.erase(options);
182}
183
184void
185Nrd::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
186{
187 nfd::ControlResponse response;
188
189 response.setCode(200);
190 response.setText("Success");
191 response.setBody(options.wireEncode());
192
193 std::cout << "Success: Name registered (" << options.getName() << ", " <<
194 options.getFaceId() << ")" << std::endl;
195 sendResponse(request.getName(), response);
196}
197
198
199void
200Nrd::insertEntry(const Interest& request, const PrefixRegOptions& options)
201{
202 // For right now, just pass the options to fib as it is,
203 // without processing flags. Later options will be first added to
204 // Rib tree, then nrd will generate fib updates based on flags and then
205 // will add next hops one by one..
206 m_managedRib.insert(options);
207 m_nfdController->fibAddNextHop(options.getName(), options.getFaceId(),
208 options.getCost(),
209 bind(&Nrd::onRegSuccess, this, request, options),
210 bind(&Nrd::onCommandError, this, _1, request, options));
211}
212
213
214void
215Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
216{
217 m_nfdController->fibRemoveNextHop(options.getName(),
218 options.getFaceId(),
219 bind(&Nrd::onUnRegSuccess, this, request, options),
220 bind(&Nrd::onCommandError, this, _1, request, options));
221}
222
223
224void
225Nrd::listen()
226{
227 std::cout << "NRD started: listening for incoming interests" << std::endl;
228 m_face.processEvents();
229}
230
231
232void
233Nrd::onControlHeaderSuccess()
234{
235 std::cout << "Local control header enabled" << std::endl;
236}
237
238
239void
240Nrd::onControlHeaderError()
241{
242 std::cout << "Error: couldn't enable local control header" << std::endl;
243 m_face.shutdown();
244}
245
246
247void
248Nrd::enableLocalControlHeader()
249{
250 Name enable("/localhost/nfd/control-header/in-faceid/enable");
251 Interest enableCommand(enable);
252
253 m_keyChain.sign(enableCommand);
254 m_face.expressInterest(enableCommand,
255 ndn::bind(&Nrd::onControlHeaderSuccess, this),
256 ndn::bind(&Nrd::onControlHeaderError, this));
257}
258
259} // namespace nrd
260} // namespace ndn