Wire up RPC plugin loading to Node.

This commit is contained in:
Adam Ierymenko 2013-07-25 17:53:57 -04:00
parent af8fcac0fc
commit 57d8730f1b
6 changed files with 102 additions and 3 deletions

View File

@ -68,6 +68,7 @@
#include "Mutex.hpp"
#include "Multicaster.hpp"
#include "CMWC4096.hpp"
#include "RPC.hpp"
#include "../version.h"
@ -210,6 +211,7 @@ Node::~Node()
{
_NodeImpl *impl = (_NodeImpl *)_impl;
delete impl->renv.rpc;
delete impl->renv.sysEnv;
delete impl->renv.topology;
delete impl->renv.sw;
@ -315,6 +317,7 @@ Node::ReasonForTermination Node::run()
_r->sw = new Switch(_r);
_r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str());
_r->sysEnv = new SysEnv(_r);
_r->rpc = new RPC(_r);
// TODO: make configurable
bool boundPort = false;
@ -338,6 +341,25 @@ Node::ReasonForTermination Node::run()
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"unknown exception during initialization");
}
try {
std::map<std::string,bool> pluginsd(Utils::listDirectory((_r->homePath + ZT_PATH_SEPARATOR_S + "plugins.d").c_str()));
for(std::map<std::string,bool>::iterator ppath(pluginsd.begin());ppath!=pluginsd.end();++ppath) {
if (!ppath->second) {
try {
std::string funcName(ppath->first.substr(0,ppath->first.rfind('.')));
LOG("loading plugins.d/%s as RPC function %s",ppath->first.c_str(),funcName.c_str());
_r->rpc->loadLocal(funcName.c_str(),(_r->homePath + ZT_PATH_SEPARATOR_S + "plugins.d" + ZT_PATH_SEPARATOR_S + ppath->first).c_str());
} catch (std::exception &exc) {
LOG("failed to load plugin plugins.d/%s: %s",ppath->first.c_str(),exc.what());
} catch ( ... ) {
LOG("failed to load plugin plugins.d/%s: (unknown exception)",ppath->first.c_str());
}
}
}
} catch ( ... ) {
TRACE("unknown exception attempting to enumerate and load plugins");
}
try {
uint64_t lastPingCheck = 0;
uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately

View File

@ -37,6 +37,8 @@
namespace ZeroTier {
#ifndef __WINDOWS__
RPC::LocalService::LocalService(const char *dllPath)
throw(std::invalid_argument) :
_handle((void *)0),
@ -111,6 +113,8 @@ std::pair< int,std::vector<std::string> > RPC::LocalService::operator()(const st
return std::pair< int,std::vector<std::string> >(rcount,results);
}
#endif // __WINDOWS__
RPC::RPC(const RuntimeEnvironment *renv) :
_r(renv)
{
@ -123,17 +127,35 @@ RPC::~RPC()
co->second.handler(co->second.arg,co->first,co->second.peer,ZT_RPC_ERROR_CANCELLED,std::vector<std::string>());
}
#ifndef __WINDOWS__
for(std::map<std::string,LocalService *>::iterator s(_rpcServices.begin());s!=_rpcServices.end();++s)
delete s->second;
#endif
}
std::pair< int,std::vector<std::string> > RPC::callLocal(const std::string &name,const std::vector<std::string> &args)
{
#ifdef __WINDOWS__
return std::pair< int,std::vector<std::string> >(ZT_RPC_ERROR_NOT_FOUND,std::vector<std::string>());
#else
Mutex::Lock _l(_rpcServices_m);
std::map<std::string,LocalService *>::iterator s(_rpcServices.find(name));
if (s == _rpcServices.end())
return std::pair< int,std::vector<std::string> >(ZT_RPC_ERROR_NOT_FOUND,std::vector<std::string>());
return ((*(s->second))(args));
#endif
}
void RPC::loadLocal(const char *name,const char *path)
throw(std::invalid_argument)
{
#ifdef __WINDOWS__
throw std::invalid_argument("RPC plugins not supported on Windows (yet?)");
#else
LocalService *s = new LocalService(path);
Mutex::Lock _l(_rpcServices_m);
_rpcServices[std::string(name)] = s;
#endif
}
uint64_t RPC::callRemote(

View File

@ -139,6 +139,16 @@ public:
*/
std::pair< int,std::vector<std::string> > callLocal(const std::string &name,const std::vector<std::string> &args);
/**
* Load a plugin
*
* @param name Name of RPC function
* @param path Path to plugin DLL
* @throws std::invalid_argument Unable to properly load or resolve symbol(s) in DLL
*/
void loadLocal(const char *name,const char *path)
throw(std::invalid_argument);
/**
* Call a remote service
*
@ -165,8 +175,10 @@ public:
private:
const RuntimeEnvironment *_r;
#ifndef __WINDOWS__
std::map<std::string,LocalService *> _rpcServices;
Mutex _rpcServices_m;
#endif
struct RemoteCallOutstanding
{

View File

@ -42,6 +42,7 @@ class Topology;
class SysEnv;
class Multicaster;
class CMWC4096;
class RPC;
/**
* Holds global state for an instance of ZeroTier::Node
@ -65,7 +66,9 @@ public:
demarc((Demarc *)0),
multicaster((Multicaster *)0),
sw((Switch *)0),
topology((Topology *)0)
topology((Topology *)0),
sysEnv((SysEnv *)0),
rpc((RPC *)0)
{
}
@ -76,6 +79,9 @@ public:
Identity identity;
// Order matters a bit here. These are constructed in this order
// and then deleted in the opposite order on Node exit.
Logger *log; // may be null
CMWC4096 *prng;
NodeConfig *nc;
@ -84,6 +90,7 @@ public:
Switch *sw;
Topology *topology;
SysEnv *sysEnv;
RPC *rpc;
};
} // namespace ZeroTier

View File

@ -29,14 +29,13 @@
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "Utils.hpp"
#include "Mutex.hpp"
#if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#endif
#ifdef _WIN32
@ -46,6 +45,9 @@
#include <sys/stat.h>
#include <openssl/rand.h>
#include "Utils.hpp"
#include "Mutex.hpp"
namespace ZeroTier {
const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
@ -214,6 +216,29 @@ const char Utils::base64DecMap[128] = {
static const char *DAY_NAMES[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
static const char *MONTH_NAMES[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
std::map<std::string,bool> Utils::listDirectory(const char *path)
{
struct dirent de;
struct dirent *dptr;
std::map<std::string,bool> r;
DIR *d = opendir(path);
if (!d)
return r;
dptr = (struct dirent *)0;
for(;;) {
if (readdir_r(d,&de,&dptr))
break;
if (dptr) {
if ((!strcmp(dptr->d_name,"."))&&(!strcmp(dptr->d_name,"..")))
r[std::string(dptr->d_name)] = (dptr->d_type == DT_DIR);
} else break;
}
return r;
}
std::string Utils::base64Encode(const void *data,unsigned int len)
{
if (!len)

View File

@ -38,6 +38,7 @@
#include <string>
#include <stdexcept>
#include <vector>
#include <map>
#include "../ext/lz4/lz4.h"
#include "../ext/lz4/lz4hc.h"
@ -58,6 +59,16 @@ namespace ZeroTier {
class Utils
{
public:
/**
* List a directory's contents
*
* @param path Path to list
* @param files Set to fill with files
* @param directories Set to fill with directories
* @return Map of entries and whether or not they are also directories (empty on failure)
*/
static std::map<std::string,bool> listDirectory(const char *path);
/**
* @param data Data to convert to hex
* @param len Length of data