mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-24 07:06:39 +00:00
Fixes to control plane, API, eliminate problematic inheritance pattern, and start on a NodeJS class for talking to the network controller.
This commit is contained in:
parent
27c5f04d68
commit
a187d290f1
1
.gitignore
vendored
1
.gitignore
vendored
@ -43,3 +43,4 @@
|
|||||||
/ui/.module-cache
|
/ui/.module-cache
|
||||||
/windows/WebUIWrapper/bin
|
/windows/WebUIWrapper/bin
|
||||||
/windows/WebUIWrapper/obj
|
/windows/WebUIWrapper/obj
|
||||||
|
node_modules
|
||||||
|
@ -560,12 +560,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
std::string &responseContentType)
|
std::string &responseContentType)
|
||||||
{
|
{
|
||||||
char json[16384];
|
char json[16384];
|
||||||
|
|
||||||
if (path.empty())
|
|
||||||
return 404;
|
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
|
||||||
if (path[0] == "network") {
|
if ((path.size() > 0)&&(path[0] == "network")) {
|
||||||
|
|
||||||
if ((path.size() >= 2)&&(path[1].length() == 16)) {
|
if ((path.size() >= 2)&&(path[1].length() == 16)) {
|
||||||
uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
|
uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
|
||||||
@ -584,15 +581,15 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
if (sqlite3_step(_sGetMember2) == SQLITE_ROW) {
|
if (sqlite3_step(_sGetMember2) == SQLITE_ROW) {
|
||||||
Utils::snprintf(json,sizeof(json),
|
Utils::snprintf(json,sizeof(json),
|
||||||
"{\n"
|
"{\n"
|
||||||
"\tnwid: \"%s\",\n"
|
"\t\"nwid\": \"%s\",\n"
|
||||||
"\taddress: \"%s\",\n"
|
"\t\"address\": \"%s\",\n"
|
||||||
"\tauthorized: %s,\n"
|
"\t\"authorized\": %s,\n"
|
||||||
"\tactiveBridge: %s,\n"
|
"\t\"activeBridge\": %s,\n"
|
||||||
"\tlastAt: \"%s\",\n"
|
"\t\"lastAt\": \"%s\",\n"
|
||||||
"\tlastSeen: %llu,\n"
|
"\t\"lastSeen\": %llu,\n"
|
||||||
"\tfirstSeen: %llu,\n"
|
"\t\"firstSeen\": %llu,\n"
|
||||||
"\tidentity: \"%s\",\n"
|
"\t\"identity\": \"%s\",\n"
|
||||||
"\tipAssignments: [",
|
"\t\"ipAssignments\": [",
|
||||||
nwids,
|
nwids,
|
||||||
addrs,
|
addrs,
|
||||||
(sqlite3_column_int(_sGetMember2,0) > 0) ? "true" : "false",
|
(sqlite3_column_int(_sGetMember2,0) > 0) ? "true" : "false",
|
||||||
@ -651,18 +648,18 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break;
|
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break;
|
||||||
default: result = "(unrecognized result code)"; break;
|
default: result = "(unrecognized result code)"; break;
|
||||||
}
|
}
|
||||||
responseBody.append(",\n\tnetconf: \"");
|
responseBody.append(",\n\t\"netconf\": \"");
|
||||||
responseBody.append(_jsonEscape(netconf.toString().c_str()));
|
responseBody.append(_jsonEscape(netconf.toString().c_str()));
|
||||||
responseBody.append("\",\n\tnetconfResult: \"");
|
responseBody.append("\",\n\t\"netconfResult\": \"");
|
||||||
responseBody.append(result);
|
responseBody.append(result);
|
||||||
responseBody.append("\",\n\tnetconfResultMessage: \"");
|
responseBody.append("\",\n\t\"netconfResultMessage\": \"");
|
||||||
responseBody.append(_jsonEscape(netconf["error"].c_str()));
|
responseBody.append(_jsonEscape(netconf["error"].c_str()));
|
||||||
responseBody.append("\"");
|
responseBody.append("\"");
|
||||||
} else {
|
} else {
|
||||||
responseBody.append(",\n\tnetconf: \"\",\n\tnetconfResult: \"INTERNAL_SERVER_ERROR\",\n\tnetconfResultMessage: \"invalid member or signing identity\"");
|
responseBody.append(",\n\t\"netconf\": \"\",\n\t\"netconfResult\": \"INTERNAL_SERVER_ERROR\",\n\t\"netconfResultMessage\": \"invalid member or signing identity\"");
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
responseBody.append(",\n\tnetconf: \"\",\n\tnetconfResult: \"INTERNAL_SERVER_ERROR\",\n\tnetconfResultMessage: \"unexpected exception\"");
|
responseBody.append(",\n\t\"netconf\": \"\",\n\t\"netconfResult\": \"INTERNAL_SERVER_ERROR\",\n\t\"netconfResultMessage\": \"unexpected exception\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,17 +676,17 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
if (sqlite3_step(_sGetNetworkById) == SQLITE_ROW) {
|
if (sqlite3_step(_sGetNetworkById) == SQLITE_ROW) {
|
||||||
Utils::snprintf(json,sizeof(json),
|
Utils::snprintf(json,sizeof(json),
|
||||||
"{\n"
|
"{\n"
|
||||||
"\tnwid: \"%s\",\n"
|
"\t\"nwid\": \"%s\",\n"
|
||||||
"\tname: \"%s\",\n"
|
"\t\"name\": \"%s\",\n"
|
||||||
"\tprivate: %s,\n"
|
"\t\"private\": %s,\n"
|
||||||
"\tenableBroadcast: %s,\n"
|
"\t\"enableBroadcast\": %s,\n"
|
||||||
"\tallowPassiveBridging: %s,\n"
|
"\t\"allowPassiveBridging\": %s,\n"
|
||||||
"\tv4AssignMode: \"%s\",\n"
|
"\t\"v4AssignMode\": \"%s\",\n"
|
||||||
"\tv6AssignMode: \"%s\",\n"
|
"\t\"v6AssignMode\": \"%s\",\n"
|
||||||
"\tmulticastLimit: %d,\n"
|
"\t\"multicastLimit\": %d,\n"
|
||||||
"\tcreationTime: %llu,\n",
|
"\t\"creationTime\": %llu,\n",
|
||||||
"\trevision: %llu,\n"
|
"\t\"revision\": %llu,\n"
|
||||||
"\amembers: [",
|
"\a\"members\": [",
|
||||||
nwids,
|
nwids,
|
||||||
_jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,0)).c_str(),
|
_jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,0)).c_str(),
|
||||||
(sqlite3_column_int(_sGetNetworkById,1) > 0) ? "true" : "false",
|
(sqlite3_column_int(_sGetNetworkById,1) > 0) ? "true" : "false",
|
||||||
@ -713,7 +710,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
responseBody.push_back('"');
|
responseBody.push_back('"');
|
||||||
firstMember = false;
|
firstMember = false;
|
||||||
}
|
}
|
||||||
responseBody.append("],\n\trelays: [");
|
responseBody.append("],\n\t\"relays\": [");
|
||||||
|
|
||||||
sqlite3_reset(_sGetRelays);
|
sqlite3_reset(_sGetRelays);
|
||||||
sqlite3_bind_text(_sGetRelays,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sGetRelays,1,nwids,16,SQLITE_STATIC);
|
||||||
@ -721,13 +718,13 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
while (sqlite3_step(_sGetRelays) == SQLITE_ROW) {
|
while (sqlite3_step(_sGetRelays) == SQLITE_ROW) {
|
||||||
responseBody.append(firstRelay ? "\n\t\t" : ",\n\t\t");
|
responseBody.append(firstRelay ? "\n\t\t" : ",\n\t\t");
|
||||||
firstRelay = false;
|
firstRelay = false;
|
||||||
responseBody.append("{address:\"");
|
responseBody.append("{\"address\":\"");
|
||||||
responseBody.append((const char *)sqlite3_column_text(_sGetRelays,0));
|
responseBody.append((const char *)sqlite3_column_text(_sGetRelays,0));
|
||||||
responseBody.append("\",phyAddress:\"");
|
responseBody.append("\",\"phyAddress\":\"");
|
||||||
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
||||||
responseBody.append("\"}");
|
responseBody.append("\"}");
|
||||||
}
|
}
|
||||||
responseBody.append("],\n\tipAssignmentPools: [");
|
responseBody.append("],\n\t\"ipAssignmentPools\": [");
|
||||||
|
|
||||||
sqlite3_reset(_sGetIpAssignmentPools2);
|
sqlite3_reset(_sGetIpAssignmentPools2);
|
||||||
sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC);
|
||||||
@ -736,69 +733,69 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t");
|
responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t");
|
||||||
firstIpAssignmentPool = false;
|
firstIpAssignmentPool = false;
|
||||||
InetAddress ipp((const void *)sqlite3_column_blob(_sGetIpAssignmentPools2,0),(sqlite3_column_int(_sGetIpAssignmentPools2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
InetAddress ipp((const void *)sqlite3_column_blob(_sGetIpAssignmentPools2,0),(sqlite3_column_int(_sGetIpAssignmentPools2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
||||||
Utils::snprintf(json,sizeof(json),"{network:\"%s\",netmaskBits:%u}",
|
Utils::snprintf(json,sizeof(json),"{\"network\":\"%s\",\"netmaskBits\":%u}",
|
||||||
_jsonEscape(ipp.toIpString()).c_str(),
|
_jsonEscape(ipp.toIpString()).c_str(),
|
||||||
ipp.netmaskBits());
|
ipp.netmaskBits());
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
responseBody.append("],\n\trules: [");
|
responseBody.append("],\n\t\"rules\": [");
|
||||||
|
|
||||||
sqlite3_reset(_sListRules);
|
sqlite3_reset(_sListRules);
|
||||||
sqlite3_bind_text(_sListRules,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sListRules,1,nwids,16,SQLITE_STATIC);
|
||||||
bool firstRule = true;
|
bool firstRule = true;
|
||||||
while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
||||||
responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
||||||
Utils::snprintf(json,sizeof(json),"\t\truleId: %lld,\n",sqlite3_column_int64(_sListRules,0));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ruleId\": %lld,\n",sqlite3_column_int64(_sListRules,0));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tnodeId: \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,2) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,2) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tvlanId: %d,\n",sqlite3_column_int(_sListRules,2));
|
Utils::snprintf(json,sizeof(json),"\t\t\"vlanId\": %d,\n",sqlite3_column_int(_sListRules,2));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,3) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,3) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tvlanPcp: %d,\n",sqlite3_column_int(_sListRules,3));
|
Utils::snprintf(json,sizeof(json),"\t\t\"vlanPcp\": %d,\n",sqlite3_column_int(_sListRules,3));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,4) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,4) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tetherType: %d,\n",sqlite3_column_int(_sListRules,4));
|
Utils::snprintf(json,sizeof(json),"\t\t\"etherType\": %d,\n",sqlite3_column_int(_sListRules,4));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,5) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,5) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tmacSource: \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,5)).toString().c_str());
|
Utils::snprintf(json,sizeof(json),"\t\t\"macSource\": \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,5)).toString().c_str());
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,6) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,6) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tmacDest: \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,6)).toString().c_str());
|
Utils::snprintf(json,sizeof(json),"\t\t\"macDest\": \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,6)).toString().c_str());
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,7) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,7) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tipSource: \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,7)).c_str());
|
Utils::snprintf(json,sizeof(json),"\t\t\"ipSource\": \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,7)).c_str());
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,8) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,8) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tipDest: \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,8)).c_str());
|
Utils::snprintf(json,sizeof(json),"\t\t\"ipDest\": \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,8)).c_str());
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,9) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,9) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tipTos: %d,\n",sqlite3_column_int(_sListRules,9));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ipTos\": %d,\n",sqlite3_column_int(_sListRules,9));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,10) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,10) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tipProtocol: %d,\n",sqlite3_column_int(_sListRules,10));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ipProtocol\": %d,\n",sqlite3_column_int(_sListRules,10));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,11) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,11) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tipSourcePort: %d,\n",sqlite3_column_int(_sListRules,11));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ipSourcePort\": %d,\n",sqlite3_column_int(_sListRules,11));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
if (sqlite3_column_type(_sListRules,12) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,12) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\tipDestPort: %d,\n",sqlite3_column_int(_sListRules,12));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ipDestPort\": %d,\n",sqlite3_column_int(_sListRules,12));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
}
|
}
|
||||||
responseBody.append("\t\taction: \"");
|
responseBody.append("\t\t\"action\": \"");
|
||||||
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sListRules,13)));
|
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sListRules,13)));
|
||||||
responseBody.append("\"\n\t}");
|
responseBody.append("\"\n\t}");
|
||||||
}
|
}
|
||||||
@ -828,7 +825,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// GET /controller returns status and API version if controller is supported
|
// GET /controller returns status and API version if controller is supported
|
||||||
Utils::snprintf(json,sizeof(json),"{\n\tcontroller: true,\n\tapiVersion: %d\n\tclock: %llu\n}",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now());
|
Utils::snprintf(json,sizeof(json),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now());
|
||||||
responseBody = json;
|
responseBody = json;
|
||||||
responseContentType = "applicaiton/json";
|
responseContentType = "applicaiton/json";
|
||||||
return 200;
|
return 200;
|
||||||
|
@ -40,17 +40,14 @@
|
|||||||
#include "../node/NetworkController.hpp"
|
#include "../node/NetworkController.hpp"
|
||||||
#include "../node/Mutex.hpp"
|
#include "../node/Mutex.hpp"
|
||||||
|
|
||||||
#include "../service/ControlPlaneSubsystem.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class SqliteNetworkController : public NetworkController,public ControlPlaneSubsystem
|
class SqliteNetworkController : public NetworkController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SqliteNetworkController(const char *dbPath);
|
SqliteNetworkController(const char *dbPath);
|
||||||
virtual ~SqliteNetworkController();
|
virtual ~SqliteNetworkController();
|
||||||
|
|
||||||
// NetworkController
|
|
||||||
virtual NetworkController::ResultCode doNetworkConfigRequest(
|
virtual NetworkController::ResultCode doNetworkConfigRequest(
|
||||||
const InetAddress &fromAddr,
|
const InetAddress &fromAddr,
|
||||||
const Identity &signingId,
|
const Identity &signingId,
|
||||||
@ -60,22 +57,21 @@ public:
|
|||||||
uint64_t haveRevision,
|
uint64_t haveRevision,
|
||||||
Dictionary &netconf);
|
Dictionary &netconf);
|
||||||
|
|
||||||
// ControlPlaneSubsystem
|
unsigned int handleControlPlaneHttpGET(
|
||||||
virtual unsigned int handleControlPlaneHttpGET(
|
|
||||||
const std::vector<std::string> &path,
|
const std::vector<std::string> &path,
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
const std::map<std::string,std::string> &urlArgs,
|
||||||
const std::map<std::string,std::string> &headers,
|
const std::map<std::string,std::string> &headers,
|
||||||
const std::string &body,
|
const std::string &body,
|
||||||
std::string &responseBody,
|
std::string &responseBody,
|
||||||
std::string &responseContentType);
|
std::string &responseContentType);
|
||||||
virtual unsigned int handleControlPlaneHttpPOST(
|
unsigned int handleControlPlaneHttpPOST(
|
||||||
const std::vector<std::string> &path,
|
const std::vector<std::string> &path,
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
const std::map<std::string,std::string> &urlArgs,
|
||||||
const std::map<std::string,std::string> &headers,
|
const std::map<std::string,std::string> &headers,
|
||||||
const std::string &body,
|
const std::string &body,
|
||||||
std::string &responseBody,
|
std::string &responseBody,
|
||||||
std::string &responseContentType);
|
std::string &responseContentType);
|
||||||
virtual unsigned int handleControlPlaneHttpDELETE(
|
unsigned int handleControlPlaneHttpDELETE(
|
||||||
const std::vector<std::string> &path,
|
const std::vector<std::string> &path,
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
const std::map<std::string,std::string> &urlArgs,
|
||||||
const std::map<std::string,std::string> &headers,
|
const std::map<std::string,std::string> &headers,
|
||||||
|
26
controller/zt1-controller-client/index.js
Normal file
26
controller/zt1-controller-client/index.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
var request = require('request');
|
||||||
|
|
||||||
|
function ZT1ControllerClient(url,authToken)
|
||||||
|
{
|
||||||
|
this.url = url;
|
||||||
|
this.authToken = authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZT1ControllerClient.prototype.status = function(callback)
|
||||||
|
{
|
||||||
|
request({
|
||||||
|
url: this.url + 'controller',
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'X-ZT1-Auth': this.authToken
|
||||||
|
}
|
||||||
|
},function(error,response,body) {
|
||||||
|
if ((error)||(response.statusCode !== 200))
|
||||||
|
return callback(error,{});
|
||||||
|
return callback(null,JSON.parse(body));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.ZT1ControllerClient = ZT1ControllerClient;
|
14
controller/zt1-controller-client/package.json
Normal file
14
controller/zt1-controller-client/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "zt1-controller-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "ZeroTier One network controller client for NodeJS",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "ZeroTier, Inc.",
|
||||||
|
"license": "BSD",
|
||||||
|
"dependencies": {
|
||||||
|
"request": "^2.55.0"
|
||||||
|
}
|
||||||
|
}
|
7
controller/zt1-controller-client/test-controller.js
Normal file
7
controller/zt1-controller-client/test-controller.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
var ZT1ControllerClient = require('./index.js').ZT1ControllerClient;
|
||||||
|
|
||||||
|
var zt1c = new ZT1ControllerClient('http://127.0.0.1:9993/','5d6181b71fae2684f9cc64ed');
|
||||||
|
|
||||||
|
zt1c.status(function(err,status) {
|
||||||
|
console.log(status);
|
||||||
|
});
|
@ -26,7 +26,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ControlPlane.hpp"
|
#include "ControlPlane.hpp"
|
||||||
#include "ControlPlaneSubsystem.hpp"
|
|
||||||
#include "OneService.hpp"
|
#include "OneService.hpp"
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
@ -34,6 +33,8 @@
|
|||||||
|
|
||||||
#include "../ext/http-parser/http_parser.h"
|
#include "../ext/http-parser/http_parser.h"
|
||||||
|
|
||||||
|
#include "../controller/SqliteNetworkController.hpp"
|
||||||
|
|
||||||
#include "../node/InetAddress.hpp"
|
#include "../node/InetAddress.hpp"
|
||||||
#include "../node/Node.hpp"
|
#include "../node/Node.hpp"
|
||||||
#include "../node/Utils.hpp"
|
#include "../node/Utils.hpp"
|
||||||
@ -444,7 +445,7 @@ unsigned int ControlPlane::handleRequest(
|
|||||||
responseContentType = "text/plain";
|
responseContentType = "text/plain";
|
||||||
scode = 200;
|
scode = 200;
|
||||||
} else {
|
} else {
|
||||||
std::map<std::string,ControlPlaneSubsystem *>::const_iterator ss(_subsystems.find(ps[0]));
|
std::map<std::string,SqliteNetworkController *>::const_iterator ss(_subsystems.find(ps[0]));
|
||||||
if (ss != _subsystems.end())
|
if (ss != _subsystems.end())
|
||||||
scode = ss->second->handleControlPlaneHttpGET(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = ss->second->handleControlPlaneHttpGET(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
@ -477,7 +478,7 @@ unsigned int ControlPlane::handleRequest(
|
|||||||
} else scode = 500;
|
} else scode = 500;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::map<std::string,ControlPlaneSubsystem *>::const_iterator ss(_subsystems.find(ps[0]));
|
std::map<std::string,SqliteNetworkController *>::const_iterator ss(_subsystems.find(ps[0]));
|
||||||
if (ss != _subsystems.end())
|
if (ss != _subsystems.end())
|
||||||
scode = ss->second->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = ss->second->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
@ -509,7 +510,7 @@ unsigned int ControlPlane::handleRequest(
|
|||||||
_node->freeQueryResult((void *)nws);
|
_node->freeQueryResult((void *)nws);
|
||||||
} else scode = 500;
|
} else scode = 500;
|
||||||
} else {
|
} else {
|
||||||
std::map<std::string,ControlPlaneSubsystem *>::const_iterator ss(_subsystems.find(ps[0]));
|
std::map<std::string,SqliteNetworkController *>::const_iterator ss(_subsystems.find(ps[0]));
|
||||||
if (ss != _subsystems.end())
|
if (ss != _subsystems.end())
|
||||||
scode = ss->second->handleControlPlaneHttpDELETE(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = ss->second->handleControlPlaneHttpDELETE(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
|
@ -40,7 +40,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
class OneService;
|
class OneService;
|
||||||
class Node;
|
class Node;
|
||||||
class ControlPlaneSubsystem;
|
class SqliteNetworkController;
|
||||||
struct InetAddress;
|
struct InetAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,7 +72,7 @@ public:
|
|||||||
* @param prefix First element in URI path
|
* @param prefix First element in URI path
|
||||||
* @param subsys Object to call for results of GET and POST/PUT operations
|
* @param subsys Object to call for results of GET and POST/PUT operations
|
||||||
*/
|
*/
|
||||||
inline void mount(const char *prefix,ControlPlaneSubsystem *subsys)
|
inline void mount(const char *prefix,SqliteNetworkController *subsys)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
_subsystems[std::string(prefix)] = subsys;
|
_subsystems[std::string(prefix)] = subsys;
|
||||||
@ -104,7 +104,7 @@ private:
|
|||||||
Node *const _node;
|
Node *const _node;
|
||||||
std::string _uiStaticPath;
|
std::string _uiStaticPath;
|
||||||
std::set<std::string> _authTokens;
|
std::set<std::string> _authTokens;
|
||||||
std::map<std::string,ControlPlaneSubsystem *> _subsystems;
|
std::map<std::string,SqliteNetworkController *> _subsystems;
|
||||||
Mutex _lock;
|
Mutex _lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* ZeroTier One - Network Virtualization Everywhere
|
|
||||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* 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_CONTROLPLANESUBSYSTEM_HPP
|
|
||||||
#define ZT_CONTROLPLANESUBSYSTEM_HPP
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for subsystems that can be mounted under the HTTP control plane
|
|
||||||
*
|
|
||||||
* Handlers should fill in responseBody and responseContentType and return
|
|
||||||
* a HTTP status code or 0 on other errors.
|
|
||||||
*/
|
|
||||||
class ControlPlaneSubsystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ControlPlaneSubsystem() {}
|
|
||||||
virtual ~ControlPlaneSubsystem() {}
|
|
||||||
|
|
||||||
virtual unsigned int handleControlPlaneHttpGET(
|
|
||||||
const std::vector<std::string> &path,
|
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
|
||||||
const std::map<std::string,std::string> &headers,
|
|
||||||
const std::string &body,
|
|
||||||
std::string &responseBody,
|
|
||||||
std::string &responseContentType) = 0;
|
|
||||||
|
|
||||||
virtual unsigned int handleControlPlaneHttpPOST(
|
|
||||||
const std::vector<std::string> &path,
|
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
|
||||||
const std::map<std::string,std::string> &headers,
|
|
||||||
const std::string &body,
|
|
||||||
std::string &responseBody,
|
|
||||||
std::string &responseContentType) = 0;
|
|
||||||
|
|
||||||
virtual unsigned int handleControlPlaneHttpDELETE(
|
|
||||||
const std::vector<std::string> &path,
|
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
|
||||||
const std::map<std::string,std::string> &headers,
|
|
||||||
const std::string &body,
|
|
||||||
std::string &responseBody,
|
|
||||||
std::string &responseContentType) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ZeroTier
|
|
||||||
|
|
||||||
#endif
|
|
@ -233,7 +233,7 @@ public:
|
|||||||
_controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S + "ui").c_str());
|
_controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S + "ui").c_str());
|
||||||
_controlPlane->addAuthToken(authToken.c_str());
|
_controlPlane->addAuthToken(authToken.c_str());
|
||||||
if (_master)
|
if (_master)
|
||||||
_controlPlane->mount("controller",reinterpret_cast<ControlPlaneSubsystem *>(_master));
|
_controlPlane->mount("controller",reinterpret_cast<SqliteNetworkController *>(_master));
|
||||||
|
|
||||||
{ // Remember networks from previous session
|
{ // Remember networks from previous session
|
||||||
std::vector<std::string> networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str()));
|
std::vector<std::string> networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str()));
|
||||||
|
@ -11,7 +11,7 @@ The JSON API supports GET, POST/PUT, and DELETE. PUT is treated as a synonym for
|
|||||||
|
|
||||||
Values POSTed to the JSON API are *extremely* type sensitive. Things *must* be of the indicated type, otherwise they will be ignored or will generate an error. Anything quoted is a string so booleans and integers must lack quotes. Booleans must be *true* or *false* and nothing else. Integers cannot contain decimal points or they are floats (and vice versa). If something seems to be getting ignored or set to a strange value, or if you receive errors, check the type of all JSON fields you are submitting against the types listed below. Unrecognized fields in JSON objects are also ignored.
|
Values POSTed to the JSON API are *extremely* type sensitive. Things *must* be of the indicated type, otherwise they will be ignored or will generate an error. Anything quoted is a string so booleans and integers must lack quotes. Booleans must be *true* or *false* and nothing else. Integers cannot contain decimal points or they are floats (and vice versa). If something seems to be getting ignored or set to a strange value, or if you receive errors, check the type of all JSON fields you are submitting against the types listed below. Unrecognized fields in JSON objects are also ignored.
|
||||||
|
|
||||||
API requests must be authenticated via an authentication token. ZeroTier One saves this token in the *authtoken.secret* file in its working directory. This token may be supplied via the *authToken* URL parameter (e.g. '?authToken=...') or via the *X-ZT1-Auth* HTTP request header. Static UI pages are the only thing the server will allow without authentication.
|
API requests must be authenticated via an authentication token. ZeroTier One saves this token in the *authtoken.secret* file in its working directory. This token may be supplied via the *auth* URL parameter (e.g. '?auth=...') or via the *X-ZT1-Auth* HTTP request header. Static UI pages are the only thing the server will allow without authentication.
|
||||||
|
|
||||||
A *jsonp* URL argument may be supplied to request JSONP encapsulation. A JSONP response is sent as a script with its JSON response payload wrapped in a call to the function name supplied as the argument to *jsonp*.
|
A *jsonp* URL argument may be supplied to request JSONP encapsulation. A JSONP response is sent as a script with its JSON response payload wrapped in a call to the function name supplied as the argument to *jsonp*.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user