c041ca36ed
Scheduler and time are imported from ndn-cpp-dev. Forwarder is using the new scheduler API. Face system is not transitioned yet. refs #1290 Change-Id: I5679cb50bbf9890a105f663b038f13951403c2b6
253 lines
6.4 KiB
C++
253 lines
6.4 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 "face/tcp-channel-factory.hpp"
|
|
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
#include "face/unix-stream-channel-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 TcpChannelFactory* g_tcpFactory;
|
|
static shared_ptr<TcpChannel> g_tcpChannel;
|
|
static shared_ptr<InternalFace> g_internalFace;
|
|
|
|
#ifdef HAVE_UNIX_SOCKETS
|
|
static UnixStreamChannelFactory* 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 TcpChannelFactory(getGlobalIoService());
|
|
g_tcpChannel = g_tcpFactory->create(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 UnixStreamChannelFactory(getGlobalIoService());
|
|
g_unixChannel = g_unixFactory->create(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);
|
|
|
|
shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd/fib").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);
|
|
}
|