summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-25 17:53:57 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-25 17:53:57 -0400
commit57d8730f1b3da3f9fe23a9fa02c8557b80bf6716 (patch)
tree3ac70dfd9d3ecabcb90a18b2aff4a5a2e5d43db4 /node
parentaf8fcac0fcfd64600a442dc4d633601e29e611ea (diff)
downloadinfinitytier-57d8730f1b3da3f9fe23a9fa02c8557b80bf6716.tar.gz
infinitytier-57d8730f1b3da3f9fe23a9fa02c8557b80bf6716.zip
Wire up RPC plugin loading to Node.
Diffstat (limited to 'node')
-rw-r--r--node/Node.cpp22
-rw-r--r--node/RPC.cpp22
-rw-r--r--node/RPC.hpp12
-rw-r--r--node/RuntimeEnvironment.hpp9
-rw-r--r--node/Utils.cpp29
-rw-r--r--node/Utils.hpp11
6 files changed, 102 insertions, 3 deletions
diff --git a/node/Node.cpp b/node/Node.cpp
index 08b08fc1..b5c23ed9 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -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;
@@ -339,6 +342,25 @@ Node::ReasonForTermination Node::run()
}
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
uint64_t lastNetworkFingerprintCheck = 0;
diff --git a/node/RPC.cpp b/node/RPC.cpp
index e6591d7d..5a9cd719 100644
--- a/node/RPC.cpp
+++ b/node/RPC.cpp
@@ -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(
diff --git a/node/RPC.hpp b/node/RPC.hpp
index e31b5f6d..669bf5ae 100644
--- a/node/RPC.hpp
+++ b/node/RPC.hpp
@@ -140,6 +140,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
*
* @param peer Peer to call on
@@ -165,8 +175,10 @@ public:
private:
const RuntimeEnvironment *_r;
+#ifndef __WINDOWS__
std::map<std::string,LocalService *> _rpcServices;
Mutex _rpcServices_m;
+#endif
struct RemoteCallOutstanding
{
diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp
index bc63543a..35c2de3f 100644
--- a/node/RuntimeEnvironment.hpp
+++ b/node/RuntimeEnvironment.hpp
@@ -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
diff --git a/node/Utils.cpp b/node/Utils.cpp
index 7b2a17af..7a4d51ba 100644
--- a/node/Utils.cpp
+++ b/node/Utils.cpp
@@ -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)
diff --git a/node/Utils.hpp b/node/Utils.hpp
index b1917b27..fbabe3d7 100644
--- a/node/Utils.hpp
+++ b/node/Utils.hpp
@@ -38,6 +38,7 @@
#include <string>
#include <stdexcept>
#include <vector>
+#include <map>
#include "../ext/lz4/lz4.h"
#include "../ext/lz4/lz4hc.h"
@@ -59,6 +60,16 @@ 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
* @return Hexadecimal string