blob: d9867fe46e29560ba88fd6757dc4149485f8608e [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"
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080014#include "face/tcp-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080015
16#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080017#include "face/unix-stream-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080018#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -070019
20namespace nfd {
21
22NFD_LOG_INIT("Main");
23
24struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080025{
Junxiao Shi09bf7c42014-01-31 11:10:25 -070026 struct TcpOutgoing
27 {
28 TcpOutgoing(std::pair<std::string, std::string> endpoint)
29 : m_endpoint(endpoint)
30 {
31 }
Junxiao Shic041ca32014-02-25 20:01:15 -070032
Junxiao Shi09bf7c42014-01-31 11:10:25 -070033 std::pair<std::string, std::string> m_endpoint;
34 std::vector<Name> m_prefixes;
35 };
36
37 bool m_showUsage;
38 std::pair<std::string, std::string> m_tcpListen;
39 std::vector<TcpOutgoing> m_tcpOutgoings;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080040 std::string m_unixListen;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070041};
42
Junxiao Shi09bf7c42014-01-31 11:10:25 -070043static ProgramOptions g_options;
44static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070045static FibManager* g_fibManager;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070046static FaceManager* g_faceManager;
Alexander Afanasyev472acbe2014-02-26 19:30:44 -080047static LocalControlHeaderManager* g_localControlHeaderManager;
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080048static TcpFactory* g_tcpFactory;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070049static shared_ptr<TcpChannel> g_tcpChannel;
50static shared_ptr<InternalFace> g_internalFace;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080051
52#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080053static UnixStreamFactory* g_unixFactory;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080054static shared_ptr<UnixStreamChannel> g_unixChannel;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080055#endif
56
Junxiao Shi09bf7c42014-01-31 11:10:25 -070057
58void
59usage(char* programName)
60{
61 printf(
62 "%s --help\n\tshow this help and exit\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080063 "%s [--tcp-listen \"0.0.0.0:6363\"] "
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080064#ifdef HAVE_UNIX_SOCKETS
65 "[--unix-listen \"/var/run/nfd.sock\"] "
66#endif
67 "[--tcp-connect \"192.0.2.1:6363\" "
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080068 "[--prefix </example>]]\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070069 "\trun forwarding daemon\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080070 "\t--tcp-listen <ip:port>: listen on IP and port\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080071#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080072 "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080073#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080074 "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
75 "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
Junxiao Shi09bf7c42014-01-31 11:10:25 -070076 "(must appear after --tcp-connect, can occur multiple times)\n"
77 "\n",
78 programName, programName
79 );
80}
81
82inline std::pair<std::string, std::string>
83parseIpPortPair(const std::string& s)
84{
85 size_t pos = s.rfind(":");
86 if (pos == std::string::npos) {
87 throw std::invalid_argument("ip:port");
88 }
Junxiao Shic041ca32014-02-25 20:01:15 -070089
Junxiao Shi09bf7c42014-01-31 11:10:25 -070090 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
91}
92
93bool
94parseCommandLine(int argc, char** argv)
95{
96 g_options.m_showUsage = false;
97 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080098 g_options.m_unixListen = "/var/run/nfd.sock";
Junxiao Shi09bf7c42014-01-31 11:10:25 -070099 g_options.m_tcpOutgoings.clear();
Junxiao Shic041ca32014-02-25 20:01:15 -0700100
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700101 while (1) {
102 int option_index = 0;
103 static ::option long_options[] = {
104 { "help" , no_argument , 0, 0 },
105 { "tcp-listen" , required_argument, 0, 0 },
106 { "tcp-connect" , required_argument, 0, 0 },
107 { "prefix" , required_argument, 0, 0 },
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800108 { "unix-listen" , required_argument, 0, 0 },
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700109 { 0 , 0 , 0, 0 }
110 };
111 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
112 if (c == -1) break;
Junxiao Shic041ca32014-02-25 20:01:15 -0700113
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700114 switch (c) {
115 case 0:
116 switch (option_index) {
117 case 0://help
118 g_options.m_showUsage = true;
119 break;
120 case 1://tcp-listen
121 g_options.m_tcpListen = parseIpPortPair(::optarg);
122 break;
123 case 2://tcp-connect
124 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
125 break;
126 case 3://prefix
127 if (g_options.m_tcpOutgoings.empty()) {
128 return false;
129 }
130 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800131 break;
132 case 4://unix-listen
133 g_options.m_unixListen = ::optarg;
134 break;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700135 }
136 break;
137 }
138 }
139 return true;
140}
141
142void
143onFaceFail(shared_ptr<Face> face, const std::string& reason)
144{
145 g_forwarder->removeFace(face);
146}
147
148void
149onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
150{
151 g_forwarder->addFace(newFace);
152 newFace->onFail += bind(&onFaceFail, newFace, _1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700153
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700154 // add nexthop on prefixes
155 if (prefixes != 0) {
156 Fib& fib = g_forwarder->getFib();
157 for (std::vector<Name>::iterator it = prefixes->begin();
158 it != prefixes->end(); ++it) {
159 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
160 fib.insert(*it);
161 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
162 fibEntry->addNextHop(newFace, 0);
163 }
164 }
165}
166
167void
168onFaceError(const std::string& reason)
169{
170 throw std::runtime_error(reason);
171}
172
173void
174initializeTcp()
175{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800176 g_tcpFactory = new TcpFactory();
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800177 g_tcpChannel = g_tcpFactory->createChannel(g_options.m_tcpListen.first,
178 g_options.m_tcpListen.second);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700179 g_tcpChannel->listen(
180 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
181 &onFaceError);
Junxiao Shic041ca32014-02-25 20:01:15 -0700182
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700183 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
184 g_options.m_tcpOutgoings.begin();
185 it != g_options.m_tcpOutgoings.end(); ++it) {
Junxiao Shic041ca32014-02-25 20:01:15 -0700186 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700187 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
188 }
189}
190
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800191#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700192void
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800193initializeUnix()
194{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800195 g_unixFactory = new UnixStreamFactory();
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800196 g_unixChannel = g_unixFactory->createChannel(g_options.m_unixListen);
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800197
198 g_unixChannel->listen(
199 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
200 &onFaceError);
201}
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800202#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800203
204void
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700205initializeMgmt()
206{
207 g_internalFace = make_shared<InternalFace>();
208 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700209
210 g_fibManager = new FibManager(g_forwarder->getFib(),
211 bind(&Forwarder::getFace, g_forwarder, _1),
212 g_internalFace);
213
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700214 g_faceManager = new FaceManager(g_forwarder->getFaceTable(), g_internalFace);
215
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800216 g_localControlHeaderManager =
217 new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
218 g_internalFace);
219
220 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700221 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700222}
223
224int
225main(int argc, char** argv)
226{
227 bool isCommandLineValid = parseCommandLine(argc, argv);
228 if (!isCommandLineValid) {
229 usage(argv[0]);
230 return 1;
231 }
232 if (g_options.m_showUsage) {
233 usage(argv[0]);
234 return 0;
235 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700236
237 g_forwarder = new Forwarder();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700238 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800239#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800240 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800241#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700242 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800243
244 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shic041ca32014-02-25 20:01:15 -0700245
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700246 try {
Junxiao Shic041ca32014-02-25 20:01:15 -0700247 getGlobalIoService().run();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700248 } catch(std::exception& ex) {
249 NFD_LOG_ERROR(ex.what());
250 return 1;
251 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700252
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800253 return 0;
254}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700255
256} // namespace nfd
257
258int
259main(int argc, char** argv)
260{
261 return nfd::main(argc, argv);
262}