blob: 46b5bd338714faf591dba4600cc301c613ea6bea [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"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070012#include "face/tcp-channel-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080013
14#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080015#include "face/unix-stream-channel-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080016#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -070017
18namespace nfd {
19
20NFD_LOG_INIT("Main");
21
22struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080023{
Junxiao Shi09bf7c42014-01-31 11:10:25 -070024 struct TcpOutgoing
25 {
26 TcpOutgoing(std::pair<std::string, std::string> endpoint)
27 : m_endpoint(endpoint)
28 {
29 }
Junxiao Shic041ca32014-02-25 20:01:15 -070030
Junxiao Shi09bf7c42014-01-31 11:10:25 -070031 std::pair<std::string, std::string> m_endpoint;
32 std::vector<Name> m_prefixes;
33 };
34
35 bool m_showUsage;
36 std::pair<std::string, std::string> m_tcpListen;
37 std::vector<TcpOutgoing> m_tcpOutgoings;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080038 std::string m_unixListen;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070039};
40
Junxiao Shi09bf7c42014-01-31 11:10:25 -070041static ProgramOptions g_options;
42static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070043static FibManager* g_fibManager;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070044static TcpChannelFactory* g_tcpFactory;
45static shared_ptr<TcpChannel> g_tcpChannel;
46static shared_ptr<InternalFace> g_internalFace;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080047
48#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080049static UnixStreamChannelFactory* g_unixFactory;
50static shared_ptr<UnixStreamChannel> g_unixChannel;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080051#endif
52
Junxiao Shi09bf7c42014-01-31 11:10:25 -070053
54void
55usage(char* programName)
56{
57 printf(
58 "%s --help\n\tshow this help and exit\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080059 "%s [--tcp-listen \"0.0.0.0:6363\"] "
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080060#ifdef HAVE_UNIX_SOCKETS
61 "[--unix-listen \"/var/run/nfd.sock\"] "
62#endif
63 "[--tcp-connect \"192.0.2.1:6363\" "
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080064 "[--prefix </example>]]\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070065 "\trun forwarding daemon\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080066 "\t--tcp-listen <ip:port>: listen on IP and port\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080067#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080068 "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080069#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080070 "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
71 "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
Junxiao Shi09bf7c42014-01-31 11:10:25 -070072 "(must appear after --tcp-connect, can occur multiple times)\n"
73 "\n",
74 programName, programName
75 );
76}
77
78inline std::pair<std::string, std::string>
79parseIpPortPair(const std::string& s)
80{
81 size_t pos = s.rfind(":");
82 if (pos == std::string::npos) {
83 throw std::invalid_argument("ip:port");
84 }
Junxiao Shic041ca32014-02-25 20:01:15 -070085
Junxiao Shi09bf7c42014-01-31 11:10:25 -070086 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
87}
88
89bool
90parseCommandLine(int argc, char** argv)
91{
92 g_options.m_showUsage = false;
93 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080094 g_options.m_unixListen = "/var/run/nfd.sock";
Junxiao Shi09bf7c42014-01-31 11:10:25 -070095 g_options.m_tcpOutgoings.clear();
Junxiao Shic041ca32014-02-25 20:01:15 -070096
Junxiao Shi09bf7c42014-01-31 11:10:25 -070097 while (1) {
98 int option_index = 0;
99 static ::option long_options[] = {
100 { "help" , no_argument , 0, 0 },
101 { "tcp-listen" , required_argument, 0, 0 },
102 { "tcp-connect" , required_argument, 0, 0 },
103 { "prefix" , required_argument, 0, 0 },
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800104 { "unix-listen" , required_argument, 0, 0 },
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700105 { 0 , 0 , 0, 0 }
106 };
107 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
108 if (c == -1) break;
Junxiao Shic041ca32014-02-25 20:01:15 -0700109
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700110 switch (c) {
111 case 0:
112 switch (option_index) {
113 case 0://help
114 g_options.m_showUsage = true;
115 break;
116 case 1://tcp-listen
117 g_options.m_tcpListen = parseIpPortPair(::optarg);
118 break;
119 case 2://tcp-connect
120 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
121 break;
122 case 3://prefix
123 if (g_options.m_tcpOutgoings.empty()) {
124 return false;
125 }
126 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800127 break;
128 case 4://unix-listen
129 g_options.m_unixListen = ::optarg;
130 break;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700131 }
132 break;
133 }
134 }
135 return true;
136}
137
138void
139onFaceFail(shared_ptr<Face> face, const std::string& reason)
140{
141 g_forwarder->removeFace(face);
142}
143
144void
145onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
146{
147 g_forwarder->addFace(newFace);
148 newFace->onFail += bind(&onFaceFail, newFace, _1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700149
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700150 // add nexthop on prefixes
151 if (prefixes != 0) {
152 Fib& fib = g_forwarder->getFib();
153 for (std::vector<Name>::iterator it = prefixes->begin();
154 it != prefixes->end(); ++it) {
155 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
156 fib.insert(*it);
157 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
158 fibEntry->addNextHop(newFace, 0);
159 }
160 }
161}
162
163void
164onFaceError(const std::string& reason)
165{
166 throw std::runtime_error(reason);
167}
168
169void
170initializeTcp()
171{
Junxiao Shic041ca32014-02-25 20:01:15 -0700172 g_tcpFactory = new TcpChannelFactory(getGlobalIoService());
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700173 g_tcpChannel = g_tcpFactory->create(g_options.m_tcpListen.first,
174 g_options.m_tcpListen.second);
175 g_tcpChannel->listen(
176 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
177 &onFaceError);
Junxiao Shic041ca32014-02-25 20:01:15 -0700178
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700179 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
180 g_options.m_tcpOutgoings.begin();
181 it != g_options.m_tcpOutgoings.end(); ++it) {
Junxiao Shic041ca32014-02-25 20:01:15 -0700182 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700183 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
184 }
185}
186
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800187#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700188void
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800189initializeUnix()
190{
Junxiao Shic041ca32014-02-25 20:01:15 -0700191 g_unixFactory = new UnixStreamChannelFactory(getGlobalIoService());
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800192 g_unixChannel = g_unixFactory->create(g_options.m_unixListen);
193
194 g_unixChannel->listen(
195 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
196 &onFaceError);
197}
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800198#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800199
200void
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700201initializeMgmt()
202{
203 g_internalFace = make_shared<InternalFace>();
204 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700205
206 g_fibManager = new FibManager(g_forwarder->getFib(),
207 bind(&Forwarder::getFace, g_forwarder, _1),
208 g_internalFace);
209
210 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd/fib").first;
211 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700212}
213
214int
215main(int argc, char** argv)
216{
217 bool isCommandLineValid = parseCommandLine(argc, argv);
218 if (!isCommandLineValid) {
219 usage(argv[0]);
220 return 1;
221 }
222 if (g_options.m_showUsage) {
223 usage(argv[0]);
224 return 0;
225 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700226
227 g_forwarder = new Forwarder();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700228 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800229#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800230 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800231#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700232 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800233
234 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shic041ca32014-02-25 20:01:15 -0700235
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700236 try {
Junxiao Shic041ca32014-02-25 20:01:15 -0700237 getGlobalIoService().run();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700238 } catch(std::exception& ex) {
239 NFD_LOG_ERROR(ex.what());
240 return 1;
241 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700242
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800243 return 0;
244}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700245
246} // namespace nfd
247
248int
249main(int argc, char** argv)
250{
251 return nfd::main(argc, argv);
252}