blob: ec64a552c05bc6ee2c8fbe7309b873e9089c9a66 [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
156 usage(const po::options_description& optionDesciption,
157 const char* programName)
158 {
159 std::cerr << "General Usage\n "
160 << programName << " --prefix=</autoreg/prefix> [--prefix=/another/prefix] ..."
161 << std::endl << std::endl;
162 std::cerr << optionDesciption << std::endl;
163 }
164
165 void
166 startProcessing()
167 {
168 std::cout << "AUTOREG prefixes: " << std::endl;
169 for (std::vector<ndn::Name>::const_iterator prefix = m_autoregPrefixes.begin();
170 prefix != m_autoregPrefixes.end();
171 ++prefix)
172 {
173 std::cout << " " << *prefix << std::endl;
174 }
175
176 if (!m_blackList.empty())
177 {
178 std::cout << "Blacklisted networks: " << std::endl;
179 for (std::vector<Network>::const_iterator network = m_blackList.begin();
180 network != m_blackList.end();
181 ++network)
182 {
183 std::cout << " " << *network << std::endl;
184 }
185 }
186
187 std::cout << "Whitelisted networks: " << std::endl;
188 for (std::vector<Network>::const_iterator network = m_whiteList.begin();
189 network != m_whiteList.end();
190 ++network)
191 {
192 std::cout << " " << *network << std::endl;
193 }
194
195 Interest interest("/localhost/nfd/faces/events");
196 interest
197 .setMustBeFresh(true)
198 .setChildSelector(1)
199 .setInterestLifetime(time::seconds(60))
200 ;
201
202 m_face.expressInterest(interest,
203 bind(&AutoregServer::onNotification, this, _2),
204 bind(&AutoregServer::onTimeout, this, _1));
205
206 boost::asio::signal_set signalSet(*m_face.ioService(), SIGINT, SIGTERM);
207 signalSet.async_wait(boost::bind(&AutoregServer::signalHandler, this));
208
209 m_face.processEvents();
210 }
211
212 int
213 main(int argc, char* argv[])
214 {
215 po::options_description optionDesciption;
216 optionDesciption.add_options()
217 ("help,h", "produce help message")
218 ("prefix,i", po::value<std::vector<ndn::Name> >(&m_autoregPrefixes)->composing(),
219 "prefix that should be automatically registered when new remote face is established")
220 ("cost,c", po::value<uint64_t>(&m_cost)->default_value(255),
221 "FIB cost which should be assigned to autoreg nexthops")
222 ("whitelist,w", po::value<std::vector<Network> >(&m_whiteList)->composing(),
223 "Whitelisted network, e.g., 192.168.2.0/24 or ::1/128")
224 ("blacklist,b", po::value<std::vector<Network> >(&m_blackList)->composing(),
225 "Blacklisted network, e.g., 192.168.2.32/30 or ::1/128")
226 ;
227
228 po::variables_map options;
229 try
230 {
231 po::store(po::command_line_parser(argc, argv).options(optionDesciption).run(), options);
232 po::notify(options);
233 }
234 catch (std::exception& e)
235 {
236 std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
237 usage(optionDesciption, argv[0]);
238 return 1;
239 }
240
241 if (options.count("help"))
242 {
243 usage(optionDesciption, argv[0]);
244 return 0;
245 }
246
247 if (m_autoregPrefixes.empty())
248 {
249 std::cerr << "ERROR: at least one --prefix must be specified" << std::endl << std::endl;
250 usage(optionDesciption, argv[0]);
251 return 2;
252 }
253
254 if (m_whiteList.empty())
255 {
256 // Allow everything
257 m_whiteList.push_back(Network::getMaxRangeV4());
258 m_whiteList.push_back(Network::getMaxRangeV6());
259 }
260
261 try
262 {
263 startProcessing();
264 }
265 catch (std::exception& e)
266 {
267 std::cerr << "ERROR: " << e.what() << std::endl;
268 return 2;
269 }
270
271 return 0;
272 }
273
274private:
275 Face m_face;
276 Controller m_controller;
277 uint64_t m_lastNotification;
278 std::vector<ndn::Name> m_autoregPrefixes;
279 uint64_t m_cost;
280 std::vector<Network> m_whiteList;
281 std::vector<Network> m_blackList;
282};
283
284} // namespace nfd
285
286int
287main(int argc, char* argv[])
288{
289 nfd::AutoregServer server;
290 return server.main(argc, argv);
291}