blob: e4ead643e7c92588336ef9556a34b5499b80cdc1 [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);
232
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800233 g_localControlHeaderManager =
234 new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
235 g_internalFace);
236
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -0700237 g_strategyChoiceManager = new StrategyChoiceManager(g_forwarder->getStrategyChoice(),
238 g_internalFace);
239
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700240 /// \todo add face manager section handler
241
242 /// \todo add parsing back when there is an official default config file
243 // config.parse(g_options.m_config);
244
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800245 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700246 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700247}
248
249int
250main(int argc, char** argv)
251{
252 bool isCommandLineValid = parseCommandLine(argc, argv);
253 if (!isCommandLineValid) {
254 usage(argv[0]);
255 return 1;
256 }
257 if (g_options.m_showUsage) {
258 usage(argv[0]);
259 return 0;
260 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700261
262 g_forwarder = new Forwarder();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700263 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800264#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800265 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800266#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700267 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800268
269 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shic041ca32014-02-25 20:01:15 -0700270
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700271 try {
Junxiao Shic041ca32014-02-25 20:01:15 -0700272 getGlobalIoService().run();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700273 } catch(std::exception& ex) {
274 NFD_LOG_ERROR(ex.what());
275 return 1;
276 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700277
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800278 return 0;
279}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700280
281} // namespace nfd
282
283int
284main(int argc, char** argv)
285{
286 return nfd::main(argc, argv);
287}