d665530904
This method accepts parsed URI object and attempts to create Face on the right channel (e.g., if hostname in URI resolved to IPv6, IPv6 TCP channel will be used). Factories that do not support 'createFace' operation will throw an exception. As of this commit, *Factory::create methods are renamed to more explicit *Factory::createChannel, and *Factory::connect to *Factory::createFace. All other Factory-specific methods should denote what exactly is created: channel, face, or multicast face. Change-Id: I6396dc84c4cd8bbcdde9f55cfac90635d99e93e9 Refs: #1195
259 lines
6.6 KiB
C++
259 lines
6.6 KiB
C++
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
/**
|
|
* Copyright (C) 2014 Named Data Networking Project
|
|
* See COPYING for copyright and distribution information.
|
|
*/
|
|
|
|
#include <getopt.h>
|
|
#include "core/logger.hpp"
|
|
#include "fw/forwarder.hpp"
|
|
#include "mgmt/internal-face.hpp"
|
|
#include "mgmt/fib-manager.hpp"
|
|
#include "mgmt/local-control-header-manager.hpp"
|
|
#include "face/tcp-factory.hpp"
|
|
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
#include "face/unix-stream-factory.hpp"
|
|
#endif
|
|
|
|
namespace nfd {
|
|
|
|
NFD_LOG_INIT("Main");
|
|
|
|
struct ProgramOptions
|
|
{
|
|
struct TcpOutgoing
|
|
{
|
|
TcpOutgoing(std::pair<std::string, std::string> endpoint)
|
|
: m_endpoint(endpoint)
|
|
{
|
|
}
|
|
|
|
std::pair<std::string, std::string> m_endpoint;
|
|
std::vector<Name> m_prefixes;
|
|
};
|
|
|
|
bool m_showUsage;
|
|
std::pair<std::string, std::string> m_tcpListen;
|
|
std::vector<TcpOutgoing> m_tcpOutgoings;
|
|
std::string m_unixListen;
|
|
};
|
|
|
|
static ProgramOptions g_options;
|
|
static Forwarder* g_forwarder;
|
|
static FibManager* g_fibManager;
|
|
static LocalControlHeaderManager* g_localControlHeaderManager;
|
|
static TcpFactory* g_tcpFactory;
|
|
static shared_ptr<TcpChannel> g_tcpChannel;
|
|
static shared_ptr<InternalFace> g_internalFace;
|
|
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
static UnixStreamFactory* g_unixFactory;
|
|
static shared_ptr<UnixStreamChannel> g_unixChannel;
|
|
#endif
|
|
|
|
|
|
void
|
|
usage(char* programName)
|
|
{
|
|
printf(
|
|
"%s --help\n\tshow this help and exit\n"
|
|
"%s [--tcp-listen \"0.0.0.0:6363\"] "
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
"[--unix-listen \"/var/run/nfd.sock\"] "
|
|
#endif
|
|
"[--tcp-connect \"192.0.2.1:6363\" "
|
|
"[--prefix </example>]]\n"
|
|
"\trun forwarding daemon\n"
|
|
"\t--tcp-listen <ip:port>: listen on IP and port\n"
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
"\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
|
|
#endif
|
|
"\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
|
|
"\t--prefix <NDN name>: add this face as nexthop to FIB entry "
|
|
"(must appear after --tcp-connect, can occur multiple times)\n"
|
|
"\n",
|
|
programName, programName
|
|
);
|
|
}
|
|
|
|
inline std::pair<std::string, std::string>
|
|
parseIpPortPair(const std::string& s)
|
|
{
|
|
size_t pos = s.rfind(":");
|
|
if (pos == std::string::npos) {
|
|
throw std::invalid_argument("ip:port");
|
|
}
|
|
|
|
return std::make_pair(s.substr(0, pos), s.substr(pos+1));
|
|
}
|
|
|
|
bool
|
|
parseCommandLine(int argc, char** argv)
|
|
{
|
|
g_options.m_showUsage = false;
|
|
g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
|
|
g_options.m_unixListen = "/var/run/nfd.sock";
|
|
g_options.m_tcpOutgoings.clear();
|
|
|
|
while (1) {
|
|
int option_index = 0;
|
|
static ::option long_options[] = {
|
|
{ "help" , no_argument , 0, 0 },
|
|
{ "tcp-listen" , required_argument, 0, 0 },
|
|
{ "tcp-connect" , required_argument, 0, 0 },
|
|
{ "prefix" , required_argument, 0, 0 },
|
|
{ "unix-listen" , required_argument, 0, 0 },
|
|
{ 0 , 0 , 0, 0 }
|
|
};
|
|
int c = getopt_long_only(argc, argv, "", long_options, &option_index);
|
|
if (c == -1) break;
|
|
|
|
switch (c) {
|
|
case 0:
|
|
switch (option_index) {
|
|
case 0://help
|
|
g_options.m_showUsage = true;
|
|
break;
|
|
case 1://tcp-listen
|
|
g_options.m_tcpListen = parseIpPortPair(::optarg);
|
|
break;
|
|
case 2://tcp-connect
|
|
g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
|
|
break;
|
|
case 3://prefix
|
|
if (g_options.m_tcpOutgoings.empty()) {
|
|
return false;
|
|
}
|
|
g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
|
|
break;
|
|
case 4://unix-listen
|
|
g_options.m_unixListen = ::optarg;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void
|
|
onFaceFail(shared_ptr<Face> face, const std::string& reason)
|
|
{
|
|
g_forwarder->removeFace(face);
|
|
}
|
|
|
|
void
|
|
onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
|
|
{
|
|
g_forwarder->addFace(newFace);
|
|
newFace->onFail += bind(&onFaceFail, newFace, _1);
|
|
|
|
// add nexthop on prefixes
|
|
if (prefixes != 0) {
|
|
Fib& fib = g_forwarder->getFib();
|
|
for (std::vector<Name>::iterator it = prefixes->begin();
|
|
it != prefixes->end(); ++it) {
|
|
std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
|
|
fib.insert(*it);
|
|
shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
|
|
fibEntry->addNextHop(newFace, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
onFaceError(const std::string& reason)
|
|
{
|
|
throw std::runtime_error(reason);
|
|
}
|
|
|
|
void
|
|
initializeTcp()
|
|
{
|
|
g_tcpFactory = new TcpFactory();
|
|
g_tcpChannel = g_tcpFactory->createChannel(g_options.m_tcpListen.first,
|
|
g_options.m_tcpListen.second);
|
|
g_tcpChannel->listen(
|
|
bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
|
|
&onFaceError);
|
|
|
|
for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
|
|
g_options.m_tcpOutgoings.begin();
|
|
it != g_options.m_tcpOutgoings.end(); ++it) {
|
|
g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
|
|
bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
void
|
|
initializeUnix()
|
|
{
|
|
g_unixFactory = new UnixStreamFactory();
|
|
g_unixChannel = g_unixFactory->createChannel(g_options.m_unixListen);
|
|
|
|
g_unixChannel->listen(
|
|
bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
|
|
&onFaceError);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
initializeMgmt()
|
|
{
|
|
g_internalFace = make_shared<InternalFace>();
|
|
g_forwarder->addFace(g_internalFace);
|
|
|
|
g_fibManager = new FibManager(g_forwarder->getFib(),
|
|
bind(&Forwarder::getFace, g_forwarder, _1),
|
|
g_internalFace);
|
|
|
|
g_localControlHeaderManager =
|
|
new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
|
|
g_internalFace);
|
|
|
|
shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
|
|
entry->addNextHop(g_internalFace, 0);
|
|
}
|
|
|
|
int
|
|
main(int argc, char** argv)
|
|
{
|
|
bool isCommandLineValid = parseCommandLine(argc, argv);
|
|
if (!isCommandLineValid) {
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
if (g_options.m_showUsage) {
|
|
usage(argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
g_forwarder = new Forwarder();
|
|
initializeTcp();
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
initializeUnix();
|
|
#endif
|
|
initializeMgmt();
|
|
|
|
/// \todo Add signal processing to gracefully terminate the app
|
|
|
|
try {
|
|
getGlobalIoService().run();
|
|
} catch(std::exception& ex) {
|
|
NFD_LOG_ERROR(ex.what());
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace nfd
|
|
|
|
int
|
|
main(int argc, char** argv)
|
|
{
|
|
return nfd::main(argc, argv);
|
|
}
|