blob: 226fbe677c254fc04f8acc4f5b67d13515abb00b [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 }
30
31 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
41static boost::asio::io_service g_ioService;
42static ProgramOptions g_options;
43static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070044static FibManager* g_fibManager;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070045static TcpChannelFactory* g_tcpFactory;
46static shared_ptr<TcpChannel> g_tcpChannel;
47static shared_ptr<InternalFace> g_internalFace;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080048
49#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080050static UnixStreamChannelFactory* g_unixFactory;
51static shared_ptr<UnixStreamChannel> g_unixChannel;
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080052#endif
53
Junxiao Shi09bf7c42014-01-31 11:10:25 -070054
55void
56usage(char* programName)
57{
58 printf(
59 "%s --help\n\tshow this help and exit\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080060 "%s [--tcp-listen \"0.0.0.0:6363\"] "
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080061#ifdef HAVE_UNIX_SOCKETS
62 "[--unix-listen \"/var/run/nfd.sock\"] "
63#endif
64 "[--tcp-connect \"192.0.2.1:6363\" "
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080065 "[--prefix </example>]]\n"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070066 "\trun forwarding daemon\n"
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080067 "\t--tcp-listen <ip:port>: listen on IP and port\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080068#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080069 "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080070#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080071 "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
72 "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
Junxiao Shi09bf7c42014-01-31 11:10:25 -070073 "(must appear after --tcp-connect, can occur multiple times)\n"
74 "\n",
75 programName, programName
76 );
77}
78
79inline std::pair<std::string, std::string>
80parseIpPortPair(const std::string& s)
81{
82 size_t pos = s.rfind(":");
83 if (pos == std::string::npos) {
84 throw std::invalid_argument("ip:port");
85 }
86
87 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
88}
89
90bool
91parseCommandLine(int argc, char** argv)
92{
93 g_options.m_showUsage = false;
94 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
Alexander Afanasyev062dfb42014-02-16 22:10:53 -080095 g_options.m_unixListen = "/var/run/nfd.sock";
Junxiao Shi09bf7c42014-01-31 11:10:25 -070096 g_options.m_tcpOutgoings.clear();
97
98 while (1) {
99 int option_index = 0;
100 static ::option long_options[] = {
101 { "help" , no_argument , 0, 0 },
102 { "tcp-listen" , required_argument, 0, 0 },
103 { "tcp-connect" , required_argument, 0, 0 },
104 { "prefix" , required_argument, 0, 0 },
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800105 { "unix-listen" , required_argument, 0, 0 },
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700106 { 0 , 0 , 0, 0 }
107 };
108 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
109 if (c == -1) break;
110
111 switch (c) {
112 case 0:
113 switch (option_index) {
114 case 0://help
115 g_options.m_showUsage = true;
116 break;
117 case 1://tcp-listen
118 g_options.m_tcpListen = parseIpPortPair(::optarg);
119 break;
120 case 2://tcp-connect
121 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
122 break;
123 case 3://prefix
124 if (g_options.m_tcpOutgoings.empty()) {
125 return false;
126 }
127 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800128 break;
129 case 4://unix-listen
130 g_options.m_unixListen = ::optarg;
131 break;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700132 }
133 break;
134 }
135 }
136 return true;
137}
138
139void
140onFaceFail(shared_ptr<Face> face, const std::string& reason)
141{
142 g_forwarder->removeFace(face);
143}
144
145void
146onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
147{
148 g_forwarder->addFace(newFace);
149 newFace->onFail += bind(&onFaceFail, newFace, _1);
150
151 // add nexthop on prefixes
152 if (prefixes != 0) {
153 Fib& fib = g_forwarder->getFib();
154 for (std::vector<Name>::iterator it = prefixes->begin();
155 it != prefixes->end(); ++it) {
156 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
157 fib.insert(*it);
158 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
159 fibEntry->addNextHop(newFace, 0);
160 }
161 }
162}
163
164void
165onFaceError(const std::string& reason)
166{
167 throw std::runtime_error(reason);
168}
169
170void
171initializeTcp()
172{
173 g_tcpFactory = new TcpChannelFactory(g_ioService);
174 g_tcpChannel = g_tcpFactory->create(g_options.m_tcpListen.first,
175 g_options.m_tcpListen.second);
176 g_tcpChannel->listen(
177 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
178 &onFaceError);
179
180 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
181 g_options.m_tcpOutgoings.begin();
182 it != g_options.m_tcpOutgoings.end(); ++it) {
183 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
184 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
185 }
186}
187
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800188#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700189void
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800190initializeUnix()
191{
192 g_unixFactory = new UnixStreamChannelFactory(g_ioService);
193 g_unixChannel = g_unixFactory->create(g_options.m_unixListen);
194
195 g_unixChannel->listen(
196 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
197 &onFaceError);
198}
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800199#endif
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800200
201void
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700202initializeMgmt()
203{
204 g_internalFace = make_shared<InternalFace>();
205 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700206
207 g_fibManager = new FibManager(g_forwarder->getFib(),
208 bind(&Forwarder::getFace, g_forwarder, _1),
209 g_internalFace);
210
211 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd/fib").first;
212 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700213}
214
215int
216main(int argc, char** argv)
217{
218 bool isCommandLineValid = parseCommandLine(argc, argv);
219 if (!isCommandLineValid) {
220 usage(argv[0]);
221 return 1;
222 }
223 if (g_options.m_showUsage) {
224 usage(argv[0]);
225 return 0;
226 }
227
228 g_forwarder = new Forwarder(g_ioService);
229 initializeTcp();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800230#ifdef HAVE_UNIX_SOCKETS
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800231 initializeUnix();
Alexander Afanasyevc78b1412014-02-19 14:08:26 -0800232#endif
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700233 initializeMgmt();
Alexander Afanasyev062dfb42014-02-16 22:10:53 -0800234
235 /// \todo Add signal processing to gracefully terminate the app
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700236
237 try {
238 g_ioService.run();
239 } catch(std::exception& ex) {
240 NFD_LOG_ERROR(ex.what());
241 return 1;
242 }
243
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800244 return 0;
245}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700246
247} // namespace nfd
248
249int
250main(int argc, char** argv)
251{
252 return nfd::main(argc, argv);
253}