blob: 541d8ffbccdad158db9679b234d89171b492655d [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"
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080015#include "face/tcp-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080016
17#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080018#include "face/unix-stream-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080019#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -070020
21namespace nfd {
22
23NFD_LOG_INIT("Main");
24
25struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080026{
Junxiao Shi09bf7c42014-01-31 11:10:25 -070027 struct TcpOutgoing
28 {
29 TcpOutgoing(std::pair<std::string, std::string> endpoint)
30 : m_endpoint(endpoint)
31 {
32 }
Junxiao Shic041ca32014-02-25 20:01:15 -070033
Junxiao Shi09bf7c42014-01-31 11:10:25 -070034 std::pair<std::string, std::string> m_endpoint;
35 std::vector<Name> m_prefixes;
36 };
37
38 bool m_showUsage;
39 std::pair<std::string, std::string> m_tcpListen;
40 std::vector<TcpOutgoing> m_tcpOutgoings;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080041 std::string m_unixListen;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070042};
43
Junxiao Shi09bf7c42014-01-31 11:10:25 -070044static ProgramOptions g_options;
45static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070046static FibManager* g_fibManager;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070047static FaceManager* g_faceManager;
Alexander Afanasyev472acbe2014-02-26 19:30:44 -080048static LocalControlHeaderManager* g_localControlHeaderManager;
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070049static StrategyChoiceManager* g_strategyChoiceManager;
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080050static TcpFactory* g_tcpFactory;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070051static shared_ptr<TcpChannel> g_tcpChannel;
52static shared_ptr<InternalFace> g_internalFace;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080053
54#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080055static UnixStreamFactory* g_unixFactory;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080056static shared_ptr<UnixStreamChannel> g_unixChannel;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080057#endif
58
Junxiao Shi09bf7c42014-01-31 11:10:25 -070059
60void
61usage(char* programName)
62{
63 printf(
64 "%s --help\n\tshow this help and exit\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080065 "%s [--tcp-listen \"0.0.0.0:6363\"] "
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080066#ifdef HAVE_UNIX_SOCKETS
67 "[--unix-listen \"/var/run/nfd.sock\"] "
68#endif
69 "[--tcp-connect \"192.0.2.1:6363\" "
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080070 "[--prefix </example>]]\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070071 "\trun forwarding daemon\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080072 "\t--tcp-listen <ip:port>: listen on IP and port\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080073#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080074 "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080075#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080076 "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
77 "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
Junxiao Shi09bf7c42014-01-31 11:10:25 -070078 "(must appear after --tcp-connect, can occur multiple times)\n"
79 "\n",
80 programName, programName
81 );
82}
83
84inline std::pair<std::string, std::string>
85parseIpPortPair(const std::string& s)
86{
87 size_t pos = s.rfind(":");
88 if (pos == std::string::npos) {
89 throw std::invalid_argument("ip:port");
90 }
Junxiao Shic041ca32014-02-25 20:01:15 -070091
Junxiao Shi09bf7c42014-01-31 11:10:25 -070092 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
93}
94
95bool
96parseCommandLine(int argc, char** argv)
97{
98 g_options.m_showUsage = false;
99 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800100 g_options.m_unixListen = "/var/run/nfd.sock";
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700101 g_options.m_tcpOutgoings.clear();
Junxiao Shic041ca32014-02-25 20:01:15 -0700102
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700103 while (1) {
104 int option_index = 0;
105 static ::option long_options[] = {
106 { "help" , no_argument , 0, 0 },
107 { "tcp-listen" , required_argument, 0, 0 },
108 { "tcp-connect" , required_argument, 0, 0 },
109 { "prefix" , required_argument, 0, 0 },
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800110 { "unix-listen" , required_argument, 0, 0 },
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700111 { 0 , 0 , 0, 0 }
112 };
113 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
114 if (c == -1) break;
Junxiao Shic041ca32014-02-25 20:01:15 -0700115
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700116 switch (c) {
117 case 0:
118 switch (option_index) {
119 case 0://help
120 g_options.m_showUsage = true;
121 break;
122 case 1://tcp-listen
123 g_options.m_tcpListen = parseIpPortPair(::optarg);
124 break;
125 case 2://tcp-connect
126 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
127 break;
128 case 3://prefix
129 if (g_options.m_tcpOutgoings.empty()) {
130 return false;
131 }
132 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800133 break;
134 case 4://unix-listen
135 g_options.m_unixListen = ::optarg;
136 break;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700137 }
138 break;
139 }
140 }
141 return true;
142}
143
144void
145onFaceFail(shared_ptr<Face> face, const std::string& reason)
146{
147 g_forwarder->removeFace(face);
148}
149
150void
151onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
152{
153 g_forwarder->addFace(newFace);
154 newFace->onFail += bind(&onFaceFail, newFace, _1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700155
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700156 // add nexthop on prefixes
157 if (prefixes != 0) {
158 Fib& fib = g_forwarder->getFib();
159 for (std::vector<Name>::iterator it = prefixes->begin();
160 it != prefixes->end(); ++it) {
161 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
162 fib.insert(*it);
163 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
164 fibEntry->addNextHop(newFace, 0);
165 }
166 }
167}
168
169void
170onFaceError(const std::string& reason)
171{
172 throw std::runtime_error(reason);
173}
174
175void
176initializeTcp()
177{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800178 g_tcpFactory = new TcpFactory();
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800179 g_tcpChannel = g_tcpFactory->createChannel(g_options.m_tcpListen.first,
180 g_options.m_tcpListen.second);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700181 g_tcpChannel->listen(
182 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
183 &onFaceError);
Junxiao Shic041ca32014-02-25 20:01:15 -0700184
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700185 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
186 g_options.m_tcpOutgoings.begin();
187 it != g_options.m_tcpOutgoings.end(); ++it) {
Junxiao Shic041ca32014-02-25 20:01:15 -0700188 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700189 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
190 }
191}
192
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800193#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700194void
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800195initializeUnix()
196{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800197 g_unixFactory = new UnixStreamFactory();
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800198 g_unixChannel = g_unixFactory->createChannel(g_options.m_unixListen);
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800199
200 g_unixChannel->listen(
201 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
202 &onFaceError);
203}
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800204#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800205
206void
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700207initializeMgmt()
208{
209 g_internalFace = make_shared<InternalFace>();
210 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700211
212 g_fibManager = new FibManager(g_forwarder->getFib(),
213 bind(&Forwarder::getFace, g_forwarder, _1),
214 g_internalFace);
215
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700216 g_faceManager = new FaceManager(g_forwarder->getFaceTable(), g_internalFace);
217
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800218 g_localControlHeaderManager =
219 new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
220 g_internalFace);
221
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -0700222 g_strategyChoiceManager = new StrategyChoiceManager(g_forwarder->getStrategyChoice(),
223 g_internalFace);
224
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800225 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700226 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700227}
228
229int
230main(int argc, char** argv)
231{
232 bool isCommandLineValid = parseCommandLine(argc, argv);
233 if (!isCommandLineValid) {
234 usage(argv[0]);
235 return 1;
236 }
237 if (g_options.m_showUsage) {
238 usage(argv[0]);
239 return 0;
240 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700241
242 g_forwarder = new Forwarder();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700243 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800244#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800245 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800246#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700247 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800248
249 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shic041ca32014-02-25 20:01:15 -0700250
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700251 try {
Junxiao Shic041ca32014-02-25 20:01:15 -0700252 getGlobalIoService().run();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700253 } catch(std::exception& ex) {
254 NFD_LOG_ERROR(ex.what());
255 return 1;
256 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700257
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800258 return 0;
259}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700260
261} // namespace nfd
262
263int
264main(int argc, char** argv)
265{
266 return nfd::main(argc, argv);
267}