blob: bdb01e63279b75381fba9c404ae2d6dc1d3344a2 [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"
13
14namespace nfd {
15
16NFD_LOG_INIT("Main");
17
18struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080019{
Junxiao Shi09bf7c42014-01-31 11:10:25 -070020 struct TcpOutgoing
21 {
22 TcpOutgoing(std::pair<std::string, std::string> endpoint)
23 : m_endpoint(endpoint)
24 {
25 }
26
27 std::pair<std::string, std::string> m_endpoint;
28 std::vector<Name> m_prefixes;
29 };
30
31 bool m_showUsage;
32 std::pair<std::string, std::string> m_tcpListen;
33 std::vector<TcpOutgoing> m_tcpOutgoings;
34};
35
36static boost::asio::io_service g_ioService;
37static ProgramOptions g_options;
38static Forwarder* g_forwarder;
Steve DiBenedetto214563c2014-02-03 19:20:36 -070039static FibManager* g_fibManager;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070040static TcpChannelFactory* g_tcpFactory;
41static shared_ptr<TcpChannel> g_tcpChannel;
42static shared_ptr<InternalFace> g_internalFace;
43
44void
45usage(char* programName)
46{
47 printf(
48 "%s --help\n\tshow this help and exit\n"
49 "%s [--tcp-listen <0.0.0.0:6363>] "
50 "[--tcp-connect <192.0.2.1:6363> [--prefix </example>]]\n"
51 "\trun forwarding daemon\n"
52 "\t--tcp-listen: listen on IP and port\n"
53 "\t--tcp-connect: connect to IP and port (can occur multiple times)\n"
54 "\t--prefix: add this face as nexthop to FIB entry "
55 "(must appear after --tcp-connect, can occur multiple times)\n"
56 "\n",
57 programName, programName
58 );
59}
60
61inline std::pair<std::string, std::string>
62parseIpPortPair(const std::string& s)
63{
64 size_t pos = s.rfind(":");
65 if (pos == std::string::npos) {
66 throw std::invalid_argument("ip:port");
67 }
68
69 return std::make_pair(s.substr(0, pos), s.substr(pos+1));
70}
71
72bool
73parseCommandLine(int argc, char** argv)
74{
75 g_options.m_showUsage = false;
76 g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
77 g_options.m_tcpOutgoings.clear();
78
79 while (1) {
80 int option_index = 0;
81 static ::option long_options[] = {
82 { "help" , no_argument , 0, 0 },
83 { "tcp-listen" , required_argument, 0, 0 },
84 { "tcp-connect" , required_argument, 0, 0 },
85 { "prefix" , required_argument, 0, 0 },
86 { 0 , 0 , 0, 0 }
87 };
88 int c = getopt_long_only(argc, argv, "", long_options, &option_index);
89 if (c == -1) break;
90
91 switch (c) {
92 case 0:
93 switch (option_index) {
94 case 0://help
95 g_options.m_showUsage = true;
96 break;
97 case 1://tcp-listen
98 g_options.m_tcpListen = parseIpPortPair(::optarg);
99 break;
100 case 2://tcp-connect
101 g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
102 break;
103 case 3://prefix
104 if (g_options.m_tcpOutgoings.empty()) {
105 return false;
106 }
107 g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
108 }
109 break;
110 }
111 }
112 return true;
113}
114
115void
116onFaceFail(shared_ptr<Face> face, const std::string& reason)
117{
118 g_forwarder->removeFace(face);
119}
120
121void
122onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
123{
124 g_forwarder->addFace(newFace);
125 newFace->onFail += bind(&onFaceFail, newFace, _1);
126
127 // add nexthop on prefixes
128 if (prefixes != 0) {
129 Fib& fib = g_forwarder->getFib();
130 for (std::vector<Name>::iterator it = prefixes->begin();
131 it != prefixes->end(); ++it) {
132 std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
133 fib.insert(*it);
134 shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
135 fibEntry->addNextHop(newFace, 0);
136 }
137 }
138}
139
140void
141onFaceError(const std::string& reason)
142{
143 throw std::runtime_error(reason);
144}
145
146void
147initializeTcp()
148{
149 g_tcpFactory = new TcpChannelFactory(g_ioService);
150 g_tcpChannel = g_tcpFactory->create(g_options.m_tcpListen.first,
151 g_options.m_tcpListen.second);
152 g_tcpChannel->listen(
153 bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
154 &onFaceError);
155
156 for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
157 g_options.m_tcpOutgoings.begin();
158 it != g_options.m_tcpOutgoings.end(); ++it) {
159 g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
160 bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
161 }
162}
163
164void
165initializeMgmt()
166{
167 g_internalFace = make_shared<InternalFace>();
168 g_forwarder->addFace(g_internalFace);
Steve DiBenedetto214563c2014-02-03 19:20:36 -0700169
170 g_fibManager = new FibManager(g_forwarder->getFib(),
171 bind(&Forwarder::getFace, g_forwarder, _1),
172 g_internalFace);
173
174 shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd/fib").first;
175 entry->addNextHop(g_internalFace, 0);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700176}
177
178int
179main(int argc, char** argv)
180{
181 bool isCommandLineValid = parseCommandLine(argc, argv);
182 if (!isCommandLineValid) {
183 usage(argv[0]);
184 return 1;
185 }
186 if (g_options.m_showUsage) {
187 usage(argv[0]);
188 return 0;
189 }
190
191 g_forwarder = new Forwarder(g_ioService);
192 initializeTcp();
193 initializeMgmt();
194
195 try {
196 g_ioService.run();
197 } catch(std::exception& ex) {
198 NFD_LOG_ERROR(ex.what());
199 return 1;
200 }
201
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800202 return 0;
203}
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700204
205} // namespace nfd
206
207int
208main(int argc, char** argv)
209{
210 return nfd::main(argc, argv);
211}