summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/Node.cpp2
-rw-r--r--node/Node.hpp2
-rw-r--r--service/ControlPlane.cpp94
-rw-r--r--service/One.cpp23
4 files changed, 97 insertions, 24 deletions
diff --git a/node/Node.cpp b/node/Node.cpp
index d6b799e9..be9eadfa 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -373,7 +373,7 @@ ZT1_PeerList *Node::peers() const
ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
{
Mutex::Lock _l(_networks_m);
- std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid));
+ std::map< uint64_t,SharedPtr<Network> >::const_iterator nw(_networks.find(nwid));
if (nw != _networks.end()) {
ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig));
nw->second->externalConfig(nc);
diff --git a/node/Node.hpp b/node/Node.hpp
index 18baccc4..95751706 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -99,7 +99,7 @@ public:
ZT1_ResultCode leave(uint64_t nwid);
ZT1_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT1_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
- uint64_t address(ZT1_Node *node) const;
+ uint64_t address() const;
void status(ZT1_NodeStatus *status) const;
ZT1_PeerList *peers() const;
ZT1_VirtualNetworkConfig *networkConfig(uint64_t nwid) const;
diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp
index 0ada25b1..dceba8d6 100644
--- a/service/ControlPlane.cpp
+++ b/service/ControlPlane.cpp
@@ -51,7 +51,7 @@ static std::string _jsonEscape(const char *s)
case '"': buf.append("\\\""); break;
case '\\': buf.append("\\\\"); break;
case '/': buf.append("\\/"); break;
- default: buf.push_back(*s); break;
+ default: buf.push_back(*p); break;
}
}
return buf;
@@ -92,6 +92,22 @@ static std::string _jsonEnumerate(const struct sockaddr_storage *ss,unsigned int
buf.push_back(']');
return buf;
}
+static std::string _jsonEnumerate(const ZT1_PeerPhysicalPath *pp,unsigned int count)
+{
+ char tmp[1024];
+ std::string buf;
+ buf.push_back('[');
+ for(unsigned int i=0;i<count;++i) {
+ if (i > 0)
+ buf.push_back(',');
+ buf.append("{\"address\":\"");
+ buf.append(_jsonEscape(reinterpret_cast<const InetAddress *>(&(pp[i].address))->toString()));
+ Utils::snprintf(tmp,sizeof(tmp),"\",\"lastSend\":%llu,\"lastReceive\":%llu,\"fixed\":%s}",pp[i].lastSend,pp[i].lastReceive,(pp[i].fixed == 0) ? "falase" : "true");
+ buf.append(tmp);
+ }
+ buf.push_back(']');
+ return buf;
+}
static void _jsonAppend(std::string &buf,const ZT1_VirtualNetworkConfig *nc)
{
char json[65536];
@@ -141,6 +157,33 @@ static void _jsonAppend(std::string &buf,const ZT1_VirtualNetworkConfig *nc)
}
static void _jsonAppend(std::string &buf,const ZT1_Peer *peer)
{
+ char json[65536];
+ const char *prole = "";
+ switch(peer->role) {
+ case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break;
+ case ZT1_PEER_ROLE_HUB: prole = "HUB"; break;
+ case ZT1_PEER_ROLE_SUPERNODE: prole = "SUPERNODE"; break;
+ }
+ Utils::snprintf(json,sizeof(json),
+ "{"
+ "\"address\": \"%.10llx\","
+ "\"versionMajor\": %d,"
+ "\"versionMinor\": %d,"
+ "\"versionRev\": %d,"
+ "\"version\": \"%d.%d.%d\","
+ "\"latency\": %u,"
+ "\"role\": \"%s\","
+ "\"paths\": %s"
+ "}",
+ peer->address,
+ peer->versionMajor,
+ peer->versionMinor,
+ peer->versionRev,
+ peer->versionMajor,peer->versionMinor,peer->versionRev,
+ peer->latency,
+ prole,
+ _jsonEnumerate(peer->paths,peer->pathCount).c_str());
+ buf.append(json);
}
ControlPlane::ControlPlane(Node *n,const std::set<std::string> atoks) :
@@ -192,6 +235,7 @@ unsigned int ControlPlane::handleRequest(
if (ps[0] == "index") {
responseContentType = "text/html";
responseBody = "<html><body>Hello World!</body></html>";
+ scode = 200;
} else if (ps[0] == "status") {
responseContentType = "application/json";
ZT1_NodeStatus status;
@@ -203,7 +247,7 @@ unsigned int ControlPlane::handleRequest(
"\"online\":%s,"
"\"versionMajor\":%d,"
"\"versionMinor\":%d,"
- "\"versionRevision\":%d,"
+ "\"versionRev\":%d,"
"\"version\":\"%d.%d.%d\""
"}",
status.address,
@@ -214,9 +258,11 @@ unsigned int ControlPlane::handleRequest(
ZEROTIER_ONE_VERSION_REVISION,
ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
responseBody = json;
+ scode = 200;
} else if (ps[0] == "config") {
responseContentType = "application/json";
responseBody = "{}"; // TODO
+ scode = 200;
} else if (ps[0] == "network") {
ZT1_VirtualNetworkList *nws = _node->networks();
if (nws) {
@@ -230,27 +276,53 @@ unsigned int ControlPlane::handleRequest(
_jsonAppend(responseBody,&(nws->networks[i]));
}
responseBody.push_back(']');
+ scode = 200;
} else if (ps.size() == 2) {
// Return a single network by ID or 404 if not found
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
- bool got = false;
for(unsigned long i=0;i<nws->networkCount;++i) {
if (nws->networks[i].nwid == wantnw) {
- got = true;
responseContentType = "application/json";
_jsonAppend(responseBody,&(nws->networks[i]));
+ scode = 200;
break;
}
}
- if (!got)
- scode = 404;
- } else {
- // Not sure what they want here, 404
- scode = 404;
- }
+ } // else 404
_node->freeQueryResult((void *)nws);
- } else scode = 500;
+ } else {
+ scode = 500;
+ }
} else if (ps[0] == "peer") {
+ ZT1_PeerList *pl = _node->peers();
+ if (pl) {
+ if (ps.size() == 1) {
+ // Return [array] of all peers
+ responseContentType = "application/json";
+ responseBody = "[";
+ for(unsigned long i=0;i<pl->peerCount;++i) {
+ if (i > 0)
+ responseBody.push_back(',');
+ _jsonAppend(responseBody,&(pl->peers[i]));
+ }
+ responseBody.push_back(']');
+ scode = 200;
+ } else if (ps.size() == 2) {
+ // Return a single peer by ID or 404 if not found
+ uint64_t wantp = Utils::hexStrToU64(ps[1].c_str());
+ for(unsigned long i=0;i<pl->peerCount;++i) {
+ if (pl->peers[i].address == wantp) {
+ responseContentType = "application/json";
+ _jsonAppend(responseBody,&(pl->peers[i]));
+ scode = 200;
+ break;
+ }
+ }
+ } // else 404
+ _node->freeQueryResult((void *)pl);
+ } else {
+ scode = 500;
+ }
}
} else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) { // PUT is weird in REST but we'll take it anyway
} else if (httpMethod == HTTP_DELETE) {
diff --git a/service/One.cpp b/service/One.cpp
index 6fbce072..08210da1 100644
--- a/service/One.cpp
+++ b/service/One.cpp
@@ -31,6 +31,7 @@
#include <string>
#include <map>
+#include <set>
#include <vector>
#include <algorithm>
@@ -188,7 +189,7 @@ public:
if (_master)
_node->setNetconfMaster((void *)_master);
- _controlPlane = new ControlPlane(_node);
+ _controlPlane = new ControlPlane(_node,std::set<std::string>());
_nextBackgroundTaskDeadline = 0;
for(;;) {
@@ -453,7 +454,7 @@ public:
std::string contentType("text/plain"); // default if not changed in handleRequest()
unsigned int scode = 404;
- if ((htc->from == InetAddress::LO4)||(htc->from == InetAddress::LO6)) {
+ if ((htc->from.ipsEqual(InetAddress::LO4))||(htc->from.ipsEqual(InetAddress::LO6))) {
try {
if (_controlPlane)
scode = _controlPlane->handleRequest(htc->parser.method,htc->url,htc->headers,htc->body,data,contentType);
@@ -467,15 +468,15 @@ public:
const char *scodestr;
switch(scode) {
- case 200: scodestr = "OK";
- case 400: scodestr = "Bad Request";
- case 401: scodestr = "Unauthorized";
- case 403: scodestr = "Forbidden";
- case 404: scodestr = "Not Found";
- case 500: scodestr = "Internal Server Error";
- case 501: scodestr = "Not Implemented";
- case 503: scodestr = "Service Unavailable";
- default: scodestr = "Error";
+ case 200: scodestr = "OK"; break;
+ case 400: scodestr = "Bad Request"; break;
+ case 401: scodestr = "Unauthorized"; break;
+ case 403: scodestr = "Forbidden"; break;
+ case 404: scodestr = "Not Found"; break;
+ case 500: scodestr = "Internal Server Error"; break;
+ case 501: scodestr = "Not Implemented"; break;
+ case 503: scodestr = "Service Unavailable"; break;
+ default: scodestr = "Error"; break;
}
Utils::snprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\n",scode,scodestr);