blob: b8165f8de9f4bd941dde2d0b9180342a67078457 [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"
Alexander Afanasyev472acbe2014-02-26 19:30:44 -080012#include "mgmt/local-control-header-manager.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070013#include "face/tcp-channel-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080014
15#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080016#include "face/unix-stream-channel-factory.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080017#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -070018
19namespace nfd {
20
21NFD_LOG_INIT("Main");
22
23struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080024{
Junxiao Shi09bf7c42014-01-31 11:10:25 -070025 struct TcpOutgoing
26 {
27 TcpOutgoing(std::pair<std::string, std::string> endpoint)
28 : m_endpoint(endpoint)
29 {
30 }
Junxiao Shic041ca32014-02-25 20:01:15 -070031
Junxiao Shi09bf7c42014-01-31 11:10:25 -070032 std::pair<std::string, std::string> m_endpoint;
33 std::vector<Name> m_prefixes;
34 };
35
36 bool m_showUsage;
37 std::pair<std::string, std::string> m_tcpListen;
38 std::vector<TcpOutgoing> m_tcpOutgoings;
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080039 std::string m_unixListen;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070040};
41
Junxiao Shi09bf7c42014-01-31 11:10:25 -070042static ProgramOptions g_options;
43static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070044static FibManager* g_fibManager;
Alexander Afanasyev472acbe2014-02-26 19:30:44 -080045static LocalControlHeaderManager* g_localControlHeaderManager;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070046static TcpChannelFactory* g_tcpFactory;
47static shared_ptr<TcpChannel> g_tcpChannel;
48static shared_ptr<InternalFace> g_internalFace;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080049
50#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080051static UnixStreamChannelFactory* g_unixFactory;
52static shared_ptr<UnixStreamChannel> g_unixChannel;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080053#endif
54
Junxiao Shi09bf7c42014-01-31 11:10:25 -070055
56void
57usage(char* programName)
58{
59 printf(
60 "%s --help\n\tshow this help and exit\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080061 "%s [--tcp-listen \"0.0.0.0:6363\"] "
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080062#ifdef HAVE_UNIX_SOCKETS
63 "[--unix-listen \"/var/run/nfd.sock\"] "
64#endif
65 "[--tcp-connect \"192.0.2.1:6363\" "
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080066 "[--prefix </example>]]\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070067 "\trun forwarding daemon\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080068 "\t--tcp-listen <ip:port>: listen on IP and port\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080069#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080070 "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080071#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080072 "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
73 "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
Junxiao Shi09bf7c42014-01-31 11:10:25 -070074 "(must appear after --tcp-connect, can occur multiple times)\n"
75 "\n",
76 programName, programName
77 );
78}
79
80inline std::pair<std::string, std::string>
81parseIpPortPair(const std::string& s)
82{
83 size_t pos = s.rfind(":");
84 if (pos == std::string::npos) {
85 throw std::invalid_argument("ip:port");
86 }
Junxiao Shic041ca32014-02-25 20:01:15 -070087
Junxiao Shi09bf7c42014-01-31 11:10:25 -070088 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
89}
90
91bool
92parseCommandLine(int argc, char** argv)
93{
94 g_options.m_showUsage = false;
95 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080096 g_options.m_unixListen = "/var/run/nfd.sock";
Junxiao Shi09bf7c42014-01-31 11:10:25 -070097 g_options.m_tcpOutgoings.clear();
Junxiao Shic041ca32014-02-25 20:01:15 -070098
Junxiao Shi09bf7c42014-01-31 11:10:25 -070099 while (1) {
100 int option_index = 0;
101 static ::option long_options[] = {
102 { "help" , no_argument , 0, 0 },
103 { "tcp-listen" , required_argument, 0, 0 },
104 { "tcp-connect" , required_argument, 0, 0 },
105 { "prefix" , required_argument, 0, 0 },
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800106 { "unix-listen" , required_argument, 0, 0 },
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700107 { 0 , 0 , 0, 0 }
108 };
109 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
110 if (c == -1) break;
Junxiao Shic041ca32014-02-25 20:01:15 -0700111
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700112 switch (c) {
113 case 0:
114 switch (option_index) {
115 case 0://help
116 g_options.m_showUsage = true;
117 break;
118 case 1://tcp-listen
119 g_options.m_tcpListen = parseIpPortPair(::optarg);
120 break;
121 case 2://tcp-connect
122 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
123 break;
124 case 3://prefix
125 if (g_options.m_tcpOutgoings.empty()) {
126 return false;
127 }
128 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800129 break;
130 case 4://unix-listen
131 g_options.m_unixListen = ::optarg;
132 break;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700133 }
134 break;
135 }
136 }
137 return true;
138}
139
140void
141onFaceFail(shared_ptr<Face> face, const std::string& reason)
142{
143 g_forwarder->removeFace(face);
144}
145
146void
147onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
148{
149 g_forwarder->addFace(newFace);
150 newFace->onFail += bind(&onFaceFail, newFace, _1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700151
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700152 // add nexthop on prefixes
153 if (prefixes != 0) {
154 Fib& fib = g_forwarder->getFib();
155 for (std::vector<Name>::iterator it = prefixes->begin();
156 it != prefixes->end(); ++it) {
157 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
158 fib.insert(*it);
159 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
160 fibEntry->addNextHop(newFace, 0);
161 }
162 }
163}
164
165void
166onFaceError(const std::string& reason)
167{
168 throw std::runtime_error(reason);
169}
170
171void
172initializeTcp()
173{
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800174 g_tcpFactory = new TcpChannelFactory();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700175 g_tcpChannel = g_tcpFactory->create(g_options.m_tcpListen.first,
176 g_options.m_tcpListen.second);
177 g_tcpChannel->listen(
178 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
179 &onFaceError);
Junxiao Shic041ca32014-02-25 20:01:15 -0700180
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700181 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
182 g_options.m_tcpOutgoings.begin();
183 it != g_options.m_tcpOutgoings.end(); ++it) {
Junxiao Shic041ca32014-02-25 20:01:15 -0700184 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700185 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
186 }
187}
188
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800189#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700190void
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800191initializeUnix()
192{
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800193 g_unixFactory = new UnixStreamChannelFactory();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800194 g_unixChannel = g_unixFactory->create(g_options.m_unixListen);
195
196 g_unixChannel->listen(
197 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
198 &onFaceError);
199}
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800200#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800201
202void
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700203initializeMgmt()
204{
205 g_internalFace = make_shared<InternalFace>();
206 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700207
208 g_fibManager = new FibManager(g_forwarder->getFib(),
209 bind(&Forwarder::getFace, g_forwarder, _1),
210 g_internalFace);
211
Alexander Afanasyev472acbe2014-02-26 19:30:44 -0800212 g_localControlHeaderManager =
213 new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
214 g_internalFace);
215
216 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700217 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700218}
219
220int
221main(int argc, char** argv)
222{
223 bool isCommandLineValid = parseCommandLine(argc, argv);
224 if (!isCommandLineValid) {
225 usage(argv[0]);
226 return 1;
227 }
228 if (g_options.m_showUsage) {
229 usage(argv[0]);
230 return 0;
231 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700232
233 g_forwarder = new Forwarder();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700234 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800235#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800236 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800237#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700238 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800239
240 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shic041ca32014-02-25 20:01:15 -0700241
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700242 try {
Junxiao Shic041ca32014-02-25 20:01:15 -0700243 getGlobalIoService().run();
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700244 } catch(std::exception& ex) {
245 NFD_LOG_ERROR(ex.what());
246 return 1;
247 }
Junxiao Shic041ca32014-02-25 20:01:15 -0700248
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800249 return 0;
250}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700251
252} // namespace nfd
253
254int
255main(int argc, char** argv)
256{
257 return nfd::main(argc, argv);
258}