From c4c5fa63d152fc30463babf82bff3cf1dfdb2eda Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 16 Apr 2015 15:51:56 -0700 Subject: [PATCH] Almost done with JSON parsing for tabular output. --- one.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/one.cpp b/one.cpp index 0bce5eefb..8ef098065 100644 --- a/one.cpp +++ b/one.cpp @@ -57,14 +57,20 @@ #include "version.h" #include "include/ZeroTierOne.h" + +#include "ext/json-parser/json.h" + #include "node/Constants.hpp" #include "node/Identity.hpp" #include "node/CertificateOfMembership.hpp" #include "node/Utils.hpp" #include "node/NetworkController.hpp" + #include "osdep/OSUtils.hpp" #include "osdep/Http.hpp" + #include "service/OneService.hpp" + #ifdef ZT_ENABLE_NETWORK_CONTROLLER #include "controller/SqliteNetworkController.hpp" #endif @@ -92,7 +98,7 @@ static void cliPrintHelp(const char *pn,FILE *out) fprintf(out," -D - ZeroTier home path for parameter auto-detect"ZT_EOL_S); fprintf(out," -p - HTTP port (default: auto)"ZT_EOL_S); fprintf(out," -T - Authentication token (default: auto)"ZT_EOL_S); - fprintf(out," -H - HTTP IP address (default: 127.0.0.1)"ZT_EOL_S""ZT_EOL_S); + //fprintf(out," -H - HTTP IP address (default: 127.0.0.1)"ZT_EOL_S""ZT_EOL_S); fprintf(out,"Available commands:"ZT_EOL_S); fprintf(out," info - Display status info"ZT_EOL_S); fprintf(out," listpeers - List all peers"ZT_EOL_S); @@ -254,6 +260,34 @@ static int cli(int argc,char **argv) printf("%s",cliFixJsonCRs(responseBody).c_str()); return 0; } else { + json_value *j = json_parse(responseBody.c_str(),responseBody.length()); + bool good = false; + if (j) { + if (j->type == json_object) { + const char *address = (const char *)0; + bool online = false; + const char *version = (const char *)0; + for(unsigned int k=0;ku.object.length;++k) { + if ((!strcmp(j->u.object.values[k].name,"address"))&&(j->u.object.values[k].value->type == json_string)) + address = j->u.object.values[k].value->u.string.ptr; + else if ((!strcmp(j->u.object.values[k].name,"version"))&&(j->u.object.values[k].value->type == json_string)) + version = j->u.object.values[k].value->u.string.ptr; + else if ((!strcmp(j->u.object.values[k].name,"online"))&&(j->u.object.values[k].value->type == json_boolean)) + online = (j->u.object.values[k].value->u.boolean != 0); + } + if ((address)&&(version)) { + printf("200 info %s %s %s"ZT_EOL_S,address,(online ? "ONLINE" : "OFFLINE"),version); + good = true; + } + } + json_value_free(j); + } + if (good) { + return 0; + } else { + printf("%u %s invalid JSON response"ZT_EOL_S,scode,command.c_str()); + return 1; + } } } else { printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); @@ -273,6 +307,88 @@ static int cli(int argc,char **argv) printf("%s",cliFixJsonCRs(responseBody).c_str()); return 0; } else { + printf("200 listpeers "ZT_EOL_S); + json_value *j = json_parse(responseBody.c_str(),responseBody.length()); + if (j) { + if (j->type == json_array) { + for(unsigned int p=0;pu.array.length;++p) { + json_value *jp = j->u.array.values[p]; + if (jp->type == json_object) { + const char *address = (const char *)0; + std::string paths; + int64_t latency = 0; + int64_t versionMajor = -1,versionMinor = -1,versionRev = -1; + const char *role = (const char *)0; + for(unsigned int k=0;ku.object.length;++k) { + if ((!strcmp(jp->u.object.values[k].name,"address"))&&(jp->u.object.values[k].value->type == json_string)) + address = jp->u.object.values[k].value->u.string.ptr; + else if ((!strcmp(jp->u.object.values[k].name,"versionMajor"))&&(jp->u.object.values[k].value->type == json_integer)) + versionMajor = jp->u.object.values[k].value->u.integer; + else if ((!strcmp(jp->u.object.values[k].name,"versionMinor"))&&(jp->u.object.values[k].value->type == json_integer)) + versionMinor = jp->u.object.values[k].value->u.integer; + else if ((!strcmp(jp->u.object.values[k].name,"versionRev"))&&(jp->u.object.values[k].value->type == json_integer)) + versionRev = jp->u.object.values[k].value->u.integer; + else if ((!strcmp(jp->u.object.values[k].name,"role"))&&(jp->u.object.values[k].value->type == json_string)) + role = jp->u.object.values[k].value->u.string.ptr; + else if ((!strcmp(jp->u.object.values[k].name,"latency"))&&(jp->u.object.values[k].value->type == json_integer)) + latency = jp->u.object.values[k].value->u.integer; + else if ((!strcmp(jp->u.object.values[k].name,"paths"))&&(jp->u.object.values[k].value->type == json_array)) { + for(unsigned int pp=0;ppu.object.values[k].value->u.array.length;++pp) { + json_value *jpath = jp->u.object.values[k].value->u.array.values[pp]; + if (jpath->type == json_object) { + const char *paddr = (const char *)0; + int64_t lastSend = 0; + int64_t lastReceive = 0; + bool fixed = false; + bool active = false; // fixed/active/inactive + for(unsigned int kk=0;kku.object.length;++kk) { + if ((!strcmp(jpath->u.object.values[kk].name,"address"))&&(jpath->u.object.values[kk].value->type == json_string)) + paddr = jpath->u.object.values[kk].value->u.string.ptr; + else if ((!strcmp(jpath->u.object.values[kk].name,"lastSend"))&&(jpath->u.object.values[kk].value->type == json_integer)) + lastSend = jpath->u.object.values[kk].value->u.integer; + else if ((!strcmp(jpath->u.object.values[kk].name,"lastReceive"))&&(jpath->u.object.values[kk].value->type == json_integer)) + lastReceive = jpath->u.object.values[kk].value->u.integer; + else if ((!strcmp(jpath->u.object.values[kk].name,"fixed"))&&(jpath->u.object.values[kk].value->type == json_boolean)) + fixed = (jpath->u.object.values[kk].value->u.boolean != 0); + else if ((!strcmp(jpath->u.object.values[kk].name,"active"))&&(jpath->u.object.values[kk].value->type == json_boolean)) + active = (jpath->u.object.values[kk].value->u.boolean != 0); + } + if (paddr) { + int64_t now = (int64_t)OSUtils::now(); + if (lastSend > 0) + lastSend = now - lastSend; + if (lastReceive > 0) + lastReceive = now - lastReceive; + char pathtmp[256]; + Utils::snprintf(pathtmp,sizeof(pathtmp),"%s;%lld;%lld;%s", + paddr, + lastSend, + lastReceive, + (fixed ? "fixed" : (active ? "active" : "inactive"))); + if (paths.length()) + paths.push_back(','); + paths.append(pathtmp); + } + } + } + } + } + if ((address)&&(role)) { + char verstr[64]; + if ((versionMajor >= 0)&&(versionMinor >= 0)&&(versionRev >= 0)) + Utils::snprintf(verstr,sizeof(verstr),"%lld.%lld.%lld",versionMajor,versionMinor,versionRev); + else { + verstr[0] = '-'; + verstr[1] = (char)0; + } + printf("200 listpeers %s %s %lld %s %s"ZT_EOL_S,address,(paths.length()) ? paths.c_str() : "-",latency,verstr,role); + } + } + } + } + json_value_free(j); + } + return 0; } } else { printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());