Files
NFD/daemon/main.cpp
T
Alexander Afanasyev d665530904 face: Adding new 'createFace' method in all Factories
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
2014-02-28 16:12:12 -08:00

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);
}