blob: 9f7bb7592669239b0e9fafd93bc2a476721b3767 [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001/* -*- 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
Junxiao Shi09bf7c42014-01-31 11:10:25 -07007#include <getopt.h>
8#include "core/logger.hpp"
9#include "fw/forwarder.hpp"
10#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070011#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070012#include "mgmt/face-manager.hpp"
Alexander Afanasyev472acbe2014-02-26 19:30:44 -080013#include "mgmt/local-control-header-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070014#include "mgmt/strategy-choice-manager.hpp"
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070015#include "mgmt/config-file.hpp"
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080016#include "face/tcp-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080017
18#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080019#include "face/unix-stream-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080020#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -070021
22namespace nfd {
23
24NFD_LOG_INIT("Main");
25
26struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080027{
Junxiao Shi09bf7c42014-01-31 11:10:25 -070028 struct TcpOutgoing
29 {
30 TcpOutgoing(std::pair<std::string, std::string> endpoint)
31 : m_endpoint(endpoint)
32 {
33 }
Junxiao Shic041ca32014-02-25 20:01:15 -070034
Junxiao Shi09bf7c42014-01-31 11:10:25 -070035 std::pair<std::string, std::string> m_endpoint;
36 std::vector<Name> m_prefixes;
37 };
38
39 bool m_showUsage;
40 std::pair<std::string, std::string> m_tcpListen;
41 std::vector<TcpOutgoing> m_tcpOutgoings;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080042 std::string m_unixListen;
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070043 std::string m_config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070044};
45
Junxiao Shi09bf7c42014-01-31 11:10:25 -070046static ProgramOptions g_options;
47static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070048static FibManager* g_fibManager;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070049static FaceManager* g_faceManager;
Alexander Afanasyev472acbe2014-02-26 19:30:44 -080050static LocalControlHeaderManager* g_localControlHeaderManager;
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070051static StrategyChoiceManager* g_strategyChoiceManager;
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080052static TcpFactory* g_tcpFactory;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070053static shared_ptr<TcpChannel> g_tcpChannel;
54static shared_ptr<InternalFace> g_internalFace;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080055
56#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080057static UnixStreamFactory* g_unixFactory;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080058static shared_ptr<UnixStreamChannel> g_unixChannel;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080059#endif
60
Junxiao Shi09bf7c42014-01-31 11:10:25 -070061
62void
63usage(char* programName)
64{
65 printf(
66 "%s --help\n\tshow this help and exit\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080067 "%s [--tcp-listen \"0.0.0.0:6363\"] "
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080068#ifdef HAVE_UNIX_SOCKETS
69 "[--unix-listen \"/var/run/nfd.sock\"] "
70#endif
71 "[--tcp-connect \"192.0.2.1:6363\" "
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070072 "[--prefix </example>]] "
73 "[--config /path/to/nfd.conf]\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070074 "\trun forwarding daemon\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080075 "\t--tcp-listen <ip:port>: listen on IP and port\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080076#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080077 "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080078#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080079 "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
80 "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
Junxiao Shi09bf7c42014-01-31 11:10:25 -070081 "(must appear after --tcp-connect, can occur multiple times)\n"
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070082 "\t--config <configuration file>]: path to configuration file\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070083 "\n",
84 programName, programName
85 );
86}
87
88inline std::pair<std::string, std::string>
89parseIpPortPair(const std::string& s)
90{
91 size_t pos = s.rfind(":");
92 if (pos == std::string::npos) {
93 throw std::invalid_argument("ip:port");
94 }
Junxiao Shic041ca32014-02-25 20:01:15 -070095
Junxiao Shi09bf7c42014-01-31 11:10:25 -070096 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
97}
98
99bool
100parseCommandLine(int argc, char** argv)
101{
102 g_options.m_showUsage = false;
103 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800104 g_options.m_unixListen = "/var/run/nfd.sock";
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700105 g_options.m_tcpOutgoings.clear();
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700106 g_options.m_config = DEFAULT_CONFIG_FILE;
Junxiao Shic041ca32014-02-25 20:01:15 -0700107
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700108 while (1) {
109 int option_index = 0;
110 static ::option long_options[] = {
111 { "help" , no_argument , 0, 0 },
112 { "tcp-listen" , required_argument, 0, 0 },
113 { "tcp-connect" , required_argument, 0, 0 },
114 { "prefix" , required_argument, 0, 0 },
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800115 { "unix-listen" , required_argument, 0, 0 },
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700116 { "config" , required_argument, 0, 0 },
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700117 { 0 , 0 , 0, 0 }
118 };
119 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
120 if (c == -1) break;
Junxiao Shic041ca32014-02-25 20:01:15 -0700121
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700122 switch (c) {
123 case 0:
124 switch (option_index) {
125 case 0://help
126 g_options.m_showUsage = true;
127 break;
128 case 1://tcp-listen
129 g_options.m_tcpListen = parseIpPortPair(::optarg);
130 break;
131 case 2://tcp-connect
132 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
133 break;
134 case 3://prefix
135 if (g_options.m_tcpOutgoings.empty()) {
136 return false;
137 }
138 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800139 break;
140 case 4://unix-listen
141 g_options.m_unixListen = ::optarg;
142 break;
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700143 case 5://config
144 g_options.m_config = ::optarg;
145 break;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700146 }
147 break;
148 }
149 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700150
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700151 return true;
152}
153
154void
155onFaceFail(shared_ptr<Face> face, const std::string& reason)
156{
157 g_forwarder->removeFace(face);
158}
159
160void
161onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
162{
163 g_forwarder->addFace(newFace);
164 newFace->onFail += bind(&onFaceFail, newFace, _1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700165
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700166 // add nexthop on prefixes
167 if (prefixes != 0) {
168 Fib& fib = g_forwarder->getFib();
169 for (std::vector<Name>::iterator it = prefixes->begin();
170 it != prefixes->end(); ++it) {
171 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
172 fib.insert(*it);
173 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
174 fibEntry->addNextHop(newFace, 0);
175 }
176 }
177}
178
179void
180onFaceError(const std::string& reason)
181{
182 throw std::runtime_error(reason);
183}
184
185void
186initializeTcp()
187{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800188 g_tcpFactory = new TcpFactory();
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800189 g_tcpChannel = g_tcpFactory->createChannel(g_options.m_tcpListen.first,
190 g_options.m_tcpListen.second);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700191 g_tcpChannel->listen(
192 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
193 &onFaceError);
Junxiao Shic041ca32014-02-25 20:01:15 -0700194
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700195 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
196 g_options.m_tcpOutgoings.begin();
197 it != g_options.m_tcpOutgoings.end(); ++it) {
Junxiao Shic041ca32014-02-25 20:01:15 -0700198 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700199 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
200 }
201}
202
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800203#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700204void
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800205initializeUnix()
206{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800207 g_unixFactory = new UnixStreamFactory();
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800208 g_unixChannel = g_unixFactory->createChannel(g_options.m_unixListen);
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800209
210 g_unixChannel->listen(
211 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
212 &onFaceError);
213}
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800214#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800215
216void
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700217initializeMgmt()
218{
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700219 ConfigFile config;
220
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700221 g_internalFace = make_shared<InternalFace>();
222 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700223
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700224 g_internalFace->getValidator().setConfigFile(config);
225
226
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700227 g_fibManager = new FibManager(g_forwarder->getFib(),
228 bind(&Forwarder::getFace, g_forwarder, _1),
229 g_internalFace);
230
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700231 g_faceManager = new FaceManager(g_forwarder->getFaceTable(), g_internalFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600232 g_faceManager->setConfigFile(config);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700233
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800234 g_localControlHeaderManager =
235 new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
236 g_internalFace);
237
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -0700238 g_strategyChoiceManager = new StrategyChoiceManager(g_forwarder->getStrategyChoice(),
239 g_internalFace);
240
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700241 /// \todo add parsing back when there is an official default config file
242 // config.parse(g_options.m_config);
243
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800244 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700245 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700246}
247
248int
249main(int argc, char** argv)
250{
251 bool isCommandLineValid = parseCommandLine(argc, argv);
252 if (!isCommandLineValid) {
253 usage(argv[0]);
254 return 1;
255 }
256 if (g_options.m_showUsage) {
257 usage(argv[0]);
258 return 0;
259 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700260
261 g_forwarder = new Forwarder();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700262 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800263#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800264 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800265#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700266 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800267
268 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shic041ca32014-02-25 20:01:15 -0700269
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700270 try {
Junxiao Shic041ca32014-02-25 20:01:15 -0700271 getGlobalIoService().run();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700272 } catch(std::exception& ex) {
273 NFD_LOG_ERROR(ex.what());
274 return 1;
275 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700276
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800277 return 0;
278}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700279
280} // namespace nfd
281
282int
283main(int argc, char** argv)
284{
285 return nfd::main(argc, argv);
286}