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