diff options
-rw-r--r-- | node/Node.cpp | 2 | ||||
-rw-r--r-- | node/Node.hpp | 2 | ||||
-rw-r--r-- | service/ControlPlane.cpp | 94 | ||||
-rw-r--r-- | service/One.cpp | 23 |
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); |