blob: ca7d1e69c1541691f74a05d90719eec57f19d79a [file] [log] [blame]
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -07001/* -*- 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 <ndn-cpp-dev/face.hpp>
8#include <ndn-cpp-dev/name.hpp>
9
10#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
11#include <ndn-cpp-dev/management/nfd-controller.hpp>
12
13#include <boost/program_options/options_description.hpp>
14#include <boost/program_options/variables_map.hpp>
15#include <boost/program_options/parsers.hpp>
16
17#include "daemon/core/face-uri.hpp"
18#include "network.hpp"
19
20namespace po = boost::program_options;
21
22namespace nfd {
23
24using namespace ndn::nfd;
25using ndn::Face;
26
27class AutoregServer
28{
29public:
30 AutoregServer()
31 : m_controller(m_face)
32 // , m_lastNotification(<undefined>)
33 , m_cost(255)
34 {
35 }
36
37 void
38 onNfdCommandSuccess(const FaceEventNotification& notification)
39 {
40 std::cerr << "SUCCEED: " << notification << std::endl;
41 }
42
43 void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070044 onNfdCommandFailure(const FaceEventNotification& notification,
45 uint32_t code, const std::string& reason)
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070046 {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070047 std::cerr << "FAILED: " << notification << " (code: " << code << ")" << std::endl;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070048 }
49
50 bool
51 isFiltered(const FaceUri& uri)
52 {
53 const std::string& scheme = uri.getScheme();
54 if (!(scheme == "udp4" || scheme == "tcp4" ||
55 scheme == "udp6" || scheme == "tcp6"))
56 return true;
57
58 boost::asio::ip::address address = boost::asio::ip::address::from_string(uri.getHost());
59
60 for (std::vector<Network>::const_iterator network = m_blackList.begin();
61 network != m_blackList.end();
62 ++network)
63 {
64 if (network->doesContain(address))
65 return true;
66 }
67
68 for (std::vector<Network>::const_iterator network = m_whiteList.begin();
69 network != m_whiteList.end();
70 ++network)
71 {
72 if (network->doesContain(address))
73 return false;
74 }
75
76 return true;
77 }
78
79 void
80 processCreateFace(const FaceEventNotification& notification)
81 {
82 FaceUri uri(notification.getUri());
83
84 if (isFiltered(uri))
85 {
86 std::cerr << "Not processing (filtered): " << notification << std::endl;
87 return;
88 }
89
90 for (std::vector<ndn::Name>::const_iterator prefix = m_autoregPrefixes.begin();
91 prefix != m_autoregPrefixes.end();
92 ++prefix)
93 {
94 std::cout << "Try auto-register: " << *prefix << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070095
96 m_controller.start<FibAddNextHopCommand>(
97 ControlParameters()
98 .setName(*prefix)
99 .setFaceId(notification.getFaceId())
100 .setCost(m_cost),
101 bind(&AutoregServer::onNfdCommandSuccess, this, notification),
102 bind(&AutoregServer::onNfdCommandFailure, this, notification, _1, _2));
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700103 }
104 }
105
106 void
107 onNotification(const Data& data)
108 {
109 m_lastNotification = data.getName().get(-1).toSegment();
110
111 // process
112 FaceEventNotification notification(data.getContent().blockFromValue());
113
114 if (notification.getEventKind() == FACE_EVENT_CREATED &&
115 !notification.isLocal() &&
116 notification.isOnDemand())
117 {
118 processCreateFace(notification);
119 }
120 else
121 {
122 std::cout << "IGNORED: " << notification << std::endl;
123 }
124
125 Name nextNotification("/localhost/nfd/faces/events");
126 nextNotification
127 .appendSegment(m_lastNotification + 1);
128
129 // no need to set freshness or child selectors
130 m_face.expressInterest(nextNotification,
131 bind(&AutoregServer::onNotification, this, _2),
132 bind(&AutoregServer::onTimeout, this, _1));
133 }
134
135 void
136 onTimeout(const Interest& timedOutInterest)
137 {
138 // re-express the timed out interest, but reset Nonce, since it has to change
139
140 // To be robust against missing notification, use ChildSelector and MustBeFresh
141 Interest interest("/localhost/nfd/faces/events");
142 interest
143 .setMustBeFresh(true)
144 .setChildSelector(1)
145 .setInterestLifetime(time::seconds(60))
146 ;
147
148 m_face.expressInterest(interest,
149 bind(&AutoregServer::onNotification, this, _2),
150 bind(&AutoregServer::onTimeout, this, _1));
151 }
152
153 void
154 signalHandler()
155 {
156 m_face.shutdown();
157 }
158
159
160
161 void
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700162 usage(std::ostream& os,
163 const po::options_description& optionDesciption,
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700164 const char* programName)
165 {
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700166 os << "Usage:\n"
167 << " " << programName << " --prefix=</autoreg/prefix> [--prefix=/another/prefix] ...\n"
168 << "\n";
169 os << optionDesciption;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700170 }
171
172 void
173 startProcessing()
174 {
175 std::cout << "AUTOREG prefixes: " << std::endl;
176 for (std::vector<ndn::Name>::const_iterator prefix = m_autoregPrefixes.begin();
177 prefix != m_autoregPrefixes.end();
178 ++prefix)
179 {
180 std::cout << " " << *prefix << std::endl;
181 }
182
183 if (!m_blackList.empty())
184 {
185 std::cout << "Blacklisted networks: " << std::endl;
186 for (std::vector<Network>::const_iterator network = m_blackList.begin();
187 network != m_blackList.end();
188 ++network)
189 {
190 std::cout << " " << *network << std::endl;
191 }
192 }
193
194 std::cout << "Whitelisted networks: " << std::endl;
195 for (std::vector<Network>::const_iterator network = m_whiteList.begin();
196 network != m_whiteList.end();
197 ++network)
198 {
199 std::cout << " " << *network << std::endl;
200 }
201
202 Interest interest("/localhost/nfd/faces/events");
203 interest
204 .setMustBeFresh(true)
205 .setChildSelector(1)
206 .setInterestLifetime(time::seconds(60))
207 ;
208
209 m_face.expressInterest(interest,
210 bind(&AutoregServer::onNotification, this, _2),
211 bind(&AutoregServer::onTimeout, this, _1));
212
213 boost::asio::signal_set signalSet(*m_face.ioService(), SIGINT, SIGTERM);
214 signalSet.async_wait(boost::bind(&AutoregServer::signalHandler, this));
215
216 m_face.processEvents();
217 }
218
219 int
220 main(int argc, char* argv[])
221 {
222 po::options_description optionDesciption;
223 optionDesciption.add_options()
224 ("help,h", "produce help message")
225 ("prefix,i", po::value<std::vector<ndn::Name> >(&m_autoregPrefixes)->composing(),
226 "prefix that should be automatically registered when new remote face is established")
227 ("cost,c", po::value<uint64_t>(&m_cost)->default_value(255),
228 "FIB cost which should be assigned to autoreg nexthops")
229 ("whitelist,w", po::value<std::vector<Network> >(&m_whiteList)->composing(),
230 "Whitelisted network, e.g., 192.168.2.0/24 or ::1/128")
231 ("blacklist,b", po::value<std::vector<Network> >(&m_blackList)->composing(),
232 "Blacklisted network, e.g., 192.168.2.32/30 or ::1/128")
233 ;
234
235 po::variables_map options;
236 try
237 {
238 po::store(po::command_line_parser(argc, argv).options(optionDesciption).run(), options);
239 po::notify(options);
240 }
241 catch (std::exception& e)
242 {
243 std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700244 usage(std::cerr, optionDesciption, argv[0]);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700245 return 1;
246 }
247
248 if (options.count("help"))
249 {
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700250 usage(std::cout, optionDesciption, argv[0]);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700251 return 0;
252 }
253
254 if (m_autoregPrefixes.empty())
255 {
256 std::cerr << "ERROR: at least one --prefix must be specified" << std::endl << std::endl;
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700257 usage(std::cerr, optionDesciption, argv[0]);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700258 return 2;
259 }
260
261 if (m_whiteList.empty())
262 {
263 // Allow everything
264 m_whiteList.push_back(Network::getMaxRangeV4());
265 m_whiteList.push_back(Network::getMaxRangeV6());
266 }
267
268 try
269 {
270 startProcessing();
271 }
272 catch (std::exception& e)
273 {
274 std::cerr << "ERROR: " << e.what() << std::endl;
275 return 2;
276 }
277
278 return 0;
279 }
280
281private:
282 Face m_face;
283 Controller m_controller;
284 uint64_t m_lastNotification;
285 std::vector<ndn::Name> m_autoregPrefixes;
286 uint64_t m_cost;
287 std::vector<Network> m_whiteList;
288 std::vector<Network> m_blackList;
289};
290
291} // namespace nfd
292
293int
294main(int argc, char* argv[])
295{
296 nfd::AutoregServer server;
297 return server.main(argc, argv);
298}