From 083ae2d0974394862735bf1ceff6a71f5e4dac64 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 25 Jul 2013 12:55:31 -0400 Subject: [PATCH] Work in progress on RPC. --- node/Network.hpp | 10 ++- node/RPC.cpp | 31 ++++++++ node/RPC.hpp | 183 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 node/RPC.cpp create mode 100644 node/RPC.hpp diff --git a/node/Network.hpp b/node/Network.hpp index 417688f06..8429cf84e 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -49,7 +49,15 @@ namespace ZeroTier { class NodeConfig; /** - * Local network endpoint + * Local membership to a network + * + * Networks configure themselves via RPC by accessing the function + * com.zerotier.one.Network.bootstrap at any supernode. This returns + * a series of key/value pairs that includes the IP address + * information for this node on the network and -- for closed + * networks -- a URL to retreive the network's membership list. + * A SHA-256 hash is also included to verify the return from this + * URL query. */ class Network : NonCopyable { diff --git a/node/RPC.cpp b/node/RPC.cpp new file mode 100644 index 000000000..2c69033ee --- /dev/null +++ b/node/RPC.cpp @@ -0,0 +1,31 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2012-2013 ZeroTier Networks LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include "RuntimeEnvironment.hpp" +#include "RPC.hpp" +#include "Switch.hpp" +#include "Topology.hpp" diff --git a/node/RPC.hpp b/node/RPC.hpp new file mode 100644 index 000000000..ac41dd6ac --- /dev/null +++ b/node/RPC.hpp @@ -0,0 +1,183 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2012-2013 ZeroTier Networks LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef _ZT_RPC_HPP +#define _ZT_RPC_HPP + +#include + +#include +#include +#include +#include + +#include "NonCopyable.hpp" +#include "Mutex.hpp" +#include "Address.hpp" + +namespace ZeroTier { + +class RuntimeEnvironment; + +/** + * Peer or method not found + */ +#define ZT_RPC_ERROR_NOT_FOUND -1 + +/** + * A runtime error occurred + */ +#define ZT_RPC_ERROR_RUNTIME -2 + +/** + * Call was expired without response from target + */ +#define ZT_RPC_ERROR_EXPIRED_NO_RESPONSE -3 + +/** + * Call was cancelled (or RPC is shutting down) + */ +#define ZT_RPC_ERROR_CANCELLED -4 + +/** + * RPC request and result handler + */ +class RPC : NonCopyable +{ +public: +#ifndef _WIN32 + /** + * A local service accessible by RPC, non-Windows only for now + * + * Each service DLL must export these functions: + * + * void ZeroTierPluginInit(); + * int ZeroTierPluginDo(unsigned int,const unsigned int *,const void **,const unsigned int **,const void ***); + * void ZeroTierPluginFree(int,const unsigned int *,const void **); + * void ZeroTierPluginDestroy(); + * + * Init is called on library load, Destroy on unload. Do() may + * be called from multiple threads concurrently, so any locking + * is the responsibility of the library. These must have C + * function signatures (extern "C" in C++). + * + * Do's arguments are: the number of paramters, the size of each parameter in bytes, + * and each parameter's contents. The last two arguments are result parameters. The + * first result parameter must be set to an array of integers describing the size of + * each result. The second is set to an array of pointers to actual results. The number + * of results (size of both arrays) is returned. If Do() returns zero or negative, + * these result paremeters are not used by the caller and don't need to be set. + * + * After the caller is done with Do()'s results, it calls ZeroTierPluginFree() to + * free them. This may also be called concurrently. Free() takes the number of + * results, the array of result sizes, and the result array. + */ + class LocalService : NonCopyable + { + public: + /** + * @param dllPath Path to DLL/shared object + * @throws std::invalid_argument Unable to properly load or resolve symbol(s) in DLL + */ + LocalService(const char *dllPath) + throw(std::invalid_argument); + + ~LocalService(); + + /** + * Call the DLL, return result + * + * @param args Input arguments + * @return Results from DLL + * @throws std::runtime_error Error calling DLL + */ + std::vector operator()(const std::vector &args) + throw(std::runtime_error); + + private: + void *_dlhandle; + }; +#endif + + RPC(const RuntimeEnvironment *renv); + ~RPC(); + + /** + * Used by PacketDecoder to call local RPC methods + * + * @param name Name of locally loaded method to call + * @param args Arguments to method + * @return Return value of method, and results (negative first item and empty vector means error) + */ + std::pair< int,std::vector > callLocal(const std::string &name,const std::vector &args) + throw(); + + /** + * Call a remote service + * + * @param peer Peer to call on + * @param name Name of remote function + * @param args Arguments to remote function + * @param handler Handler to call on result + * @param arg First argument to handler + * @return Call ID (packet ID of sent packet) + */ + uint64_t callRemote( + const Address &peer, + const std::string &name, + const std::vector &args, + void (*handler)(void *,uint64_t,const Address &,int,const std::vector &), + void *arg) + throw(std::invalid_argument); + + /** + * Periodically called to clean up, such as by expiring remote calls + */ + void clean(); + +private: + const RuntimeEnvironment *_r; + + std::map _rpcServices; + Mutex _rpcServices_m; + + struct RemoteCallOutstanding + { + uint64_t callTime; + Address peer; + std::string name; + std::vector &args; + void (*handler)(void *,uint64_t,const Address &,int,const std::vector &); + void *arg; + }; + std::map _remoteCallsOutstanding; + Mutex _remoteCallsOutstanding_m; +}; + +} // namespace ZeroTier + +#endif