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