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 "Mutex.hpp"
#include "Multicaster.hpp" #include "Multicaster.hpp"
#include "CMWC4096.hpp" #include "CMWC4096.hpp"
#include "RPC.hpp"
#include "../version.h" #include "../version.h"
@ -210,6 +211,7 @@ Node::~Node()
{ {
_NodeImpl *impl = (_NodeImpl *)_impl; _NodeImpl *impl = (_NodeImpl *)_impl;
delete impl->renv.rpc;
delete impl->renv.sysEnv; delete impl->renv.sysEnv;
delete impl->renv.topology; delete impl->renv.topology;
delete impl->renv.sw; delete impl->renv.sw;
@ -315,6 +317,7 @@ Node::ReasonForTermination Node::run()
_r->sw = new Switch(_r); _r->sw = new Switch(_r);
_r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str()); _r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str());
_r->sysEnv = new SysEnv(_r); _r->sysEnv = new SysEnv(_r);
_r->rpc = new RPC(_r);
// TODO: make configurable // TODO: make configurable
bool boundPort = false; bool boundPort = false;
@ -338,6 +341,25 @@ Node::ReasonForTermination Node::run()
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"unknown exception during initialization"); 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 { try {
uint64_t lastPingCheck = 0; uint64_t lastPingCheck = 0;
uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately

View file

@ -37,6 +37,8 @@
namespace ZeroTier { namespace ZeroTier {
#ifndef __WINDOWS__
RPC::LocalService::LocalService(const char *dllPath) RPC::LocalService::LocalService(const char *dllPath)
throw(std::invalid_argument) : throw(std::invalid_argument) :
_handle((void *)0), _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); return std::pair< int,std::vector<std::string> >(rcount,results);
} }
#endif // __WINDOWS__
RPC::RPC(const RuntimeEnvironment *renv) : RPC::RPC(const RuntimeEnvironment *renv) :
_r(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>()); 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) for(std::map<std::string,LocalService *>::iterator s(_rpcServices.begin());s!=_rpcServices.end();++s)
delete s->second; delete s->second;
#endif
} }
std::pair< int,std::vector<std::string> > RPC::callLocal(const std::string &name,const std::vector<std::string> &args) 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); Mutex::Lock _l(_rpcServices_m);
std::map<std::string,LocalService *>::iterator s(_rpcServices.find(name)); std::map<std::string,LocalService *>::iterator s(_rpcServices.find(name));
if (s == _rpcServices.end()) if (s == _rpcServices.end())
return std::pair< int,std::vector<std::string> >(ZT_RPC_ERROR_NOT_FOUND,std::vector<std::string>()); return std::pair< int,std::vector<std::string> >(ZT_RPC_ERROR_NOT_FOUND,std::vector<std::string>());
return ((*(s->second))(args)); 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( 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); 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 * Call a remote service
* *
@ -165,8 +175,10 @@ public:
private: private:
const RuntimeEnvironment *_r; const RuntimeEnvironment *_r;
#ifndef __WINDOWS__
std::map<std::string,LocalService *> _rpcServices; std::map<std::string,LocalService *> _rpcServices;
Mutex _rpcServices_m; Mutex _rpcServices_m;
#endif
struct RemoteCallOutstanding struct RemoteCallOutstanding
{ {

View file

@ -42,6 +42,7 @@ class Topology;
class SysEnv; class SysEnv;
class Multicaster; class Multicaster;
class CMWC4096; class CMWC4096;
class RPC;
/** /**
* Holds global state for an instance of ZeroTier::Node * Holds global state for an instance of ZeroTier::Node
@ -65,7 +66,9 @@ public:
demarc((Demarc *)0), demarc((Demarc *)0),
multicaster((Multicaster *)0), multicaster((Multicaster *)0),
sw((Switch *)0), sw((Switch *)0),
topology((Topology *)0) topology((Topology *)0),
sysEnv((SysEnv *)0),
rpc((RPC *)0)
{ {
} }
@ -76,6 +79,9 @@ public:
Identity identity; 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 Logger *log; // may be null
CMWC4096 *prng; CMWC4096 *prng;
NodeConfig *nc; NodeConfig *nc;
@ -84,6 +90,7 @@ public:
Switch *sw; Switch *sw;
Topology *topology; Topology *topology;
SysEnv *sysEnv; SysEnv *sysEnv;
RPC *rpc;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -29,14 +29,13 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include "Utils.hpp"
#include "Mutex.hpp"
#if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) #if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <dirent.h>
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -46,6 +45,9 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include "Utils.hpp"
#include "Mutex.hpp"
namespace ZeroTier { namespace ZeroTier {
const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; 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 *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" }; 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) std::string Utils::base64Encode(const void *data,unsigned int len)
{ {
if (!len) if (!len)

View file

@ -38,6 +38,7 @@
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include <map>
#include "../ext/lz4/lz4.h" #include "../ext/lz4/lz4.h"
#include "../ext/lz4/lz4hc.h" #include "../ext/lz4/lz4hc.h"
@ -58,6 +59,16 @@ namespace ZeroTier {
class Utils class Utils
{ {
public: 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 data Data to convert to hex
* @param len Length of data * @param len Length of data