From 3aa3cee61c7790957204fdeb56a0eb0a7e902206 Mon Sep 17 00:00:00 2001 From: /jdi/ Date: Sat, 17 Oct 2015 19:43:21 +0200 Subject: [PATCH] json parser --- src/Options.h | 27 +++--- src/Packet.cpp | 6 +- src/Packet.h | 2 +- src/Program.cpp | 24 +++--- src/Socket.cpp | 5 +- src/Switch.cpp | 221 +++++++++++++++++------------------------------- src/Switch.h | 33 +------- 7 files changed, 114 insertions(+), 204 deletions(-) diff --git a/src/Options.h b/src/Options.h index a5484a4..af207ce 100644 --- a/src/Options.h +++ b/src/Options.h @@ -25,23 +25,24 @@ -u --user <[password:]username>\n\ -p --password \n\ Login with Username and Password\n\ - -f --file Not yet implemented:.choose a settings file\n\ + -f --file choose a settings file\n\ -t --timeout Not yet implemented\n\ -w --wait Not yet implemented: blocking until operation is completed\n\ -s --permanent Not yet implemented: make changes immediately permanent\n\n\ Command Summary:\n\ - help This help text\n\ - list list all connected switches\n\ - sniff capture and display all incoming or outgoing packets\n\ - depending on the --reverse option\n\ - encode use encoding algorithm on hex data separated by colon\n\ - get Not yet implemented\n\ - set Not yet implemented\n\ - save Not yet implemented: save config to file\n\ - restore Not yet implemented: restore onfig from file\n\ - flash Not yet implemented: replace firmware\n\ - reboot Not yet implemented\n\ - reset Not yet implemented\n\n\ + help This help text\n\ + list list all connected switches\n\ + sniff [type:] []\n\ + capture and display all incoming or outgoing packets\n\ + depending on the --reverse option\n\ + encode use encoding algorithm on hex data separated by colon\n\ + get Not yet implemented\n\ + set Not yet implemented\n\ + save Not yet implemented: save config to file\n\ + restore Not yet implemented: restore onfig from file\n\ + flash Not yet implemented: replace firmware\n\ + reboot Not yet implemented\n\ + reset Not yet implemented\n\n\ ### for questions please contact ###\n\n" #define FLAG_HEX 1 diff --git a/src/Packet.cpp b/src/Packet.cpp index db4cf4c..6f2fbff 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -143,8 +143,10 @@ std::string Packet::opCodeToString() { return "GET"; case SET: return "SET"; - case RECEIVE: - return "RECEIVE"; + case LOGIN: + return "LOGIN"; + case RETURN: + return "RETURN"; case READ5: return "READ5"; default: diff --git a/src/Packet.h b/src/Packet.h index 6dd7b13..a253d38 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -16,7 +16,7 @@ class Packet { public: enum OpCode { - DISCOVERY, GET, SET, READ4,RECEIVE, READ5 + DISCOVERY, GET, SET, LOGIN, RETURN, READ5 }; Packet(OpCode); void encode(bytes&); diff --git a/src/Program.cpp b/src/Program.cpp index ab20353..fd9e7f5 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -9,6 +9,7 @@ #include "Options.h" #include "Program.h" +#include "File.h" #include "Host.h" #include "Socket.h" #include "Switch.h" @@ -45,6 +46,8 @@ int Program::list() { datasets d =a.getPayload(); Switch s = Switch(); s.parse(d); + File f; + f.write("config.json", s.toString()); std::cout <<"Devices:\n\t"<0) { - std::cout< -//#include -//#include #include #include #include @@ -75,7 +72,7 @@ void Socket::listen() { listen(); } else { data.resize(bytes_recvd); - Packet p = Packet(Packet::RECEIVE); + Packet p = Packet(Packet::RETURN); p.encode(data); p.parse(data); datasets l = p.getPayload(); diff --git a/src/Switch.cpp b/src/Switch.cpp index fae577d..1d6e9cd 100644 --- a/src/Switch.cpp +++ b/src/Switch.cpp @@ -9,6 +9,7 @@ #include "Types.h" #include "Switch.h" #include "Lookup.h" +#include "jsonNode.h" #include "Options.h" int Switch::parse(datasets arr) { @@ -52,166 +53,102 @@ int Switch::parse(dataset d) { int Switch::parse(std::string str) { - if (json.Parse(str.c_str()).HasParseError()) - return 1; + if (json.Parse(str.c_str()).HasParseError()) + return 1; if (options.flags & FLAG_DEBUG) - std::cout<<"\nParsing to document succeeded.\n"; + std::cout << "\nParsing to document succeeded.\n"; + + if (json.IsObject()) { + if (json.HasMember("hostname")) + settings.hostname = json["hostname"].GetString(); + if (json.HasMember("type")) + device.type = json["type"].GetString(); + if (json.HasMember("hardware_version")) + device.hardware_version = json["hardware_version"].GetString(); + if (json.HasMember("firmware_version")) + device.hardware_version = json["firmware_version"].GetString(); + + } + /* + json.AddMember("ports", jsonNode(ports, json), allocator); + json.AddMember("vlans", jsonNode(vlans, json), allocator); + */ + // Since version 0.2, you can use single lookup to check the existing of member and its value: + /* + rapidjson::Value::MemberIterator hello = json.FindMember("hello"); + assert(hello != json.MemberEnd()); + assert(hello->value.IsString()); + assert(strcmp("world", hello->value.GetString()) == 0); + (void) hello; + assert(json["t"].IsBool()); // JSON true/false are bool. Can also uses more specific function IsTrue(). + printf("t = %s\n", json["t"].GetBool() ? "true" : "false"); + assert(json["f"].IsBool()); + printf("f = %s\n", json["f"].GetBool() ? "true" : "false"); + printf("n = %s\n", json["n"].IsNull() ? "null" : "?"); + assert(json["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type. + assert(json["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true. + printf("i = %d\n", json["i"].GetInt()); // Alternative (int)document["i"] + assert(json["pi"].IsNumber()); + assert(json["pi"].IsDouble()); + printf("pi = %g\n", json["pi"].GetDouble()); + { + const rapidjson::Value& a = json["a"]; // Using a reference for consecutive access is handy and faster. + assert(a.IsArray()); + for (rapidjson::SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t. + printf("a[%d] = %d\n", i, a[i].GetInt()); + int y = a[0].GetInt(); + (void) y; + // Iterating array with iterators + printf("a = "); + for (rapidjson::Value::ConstValueIterator itr = a.Begin(); + itr != a.End(); ++itr) + printf("%d ", itr->GetInt()); + printf("\n"); + } - - - - - - - - - - - - - - //////////////////////////////////////////////////////////////////////////// - // 2. Access values in document. - - printf("\nAccess values in document:\n"); - assert(json.IsObject()); // Document is a JSON value represents the root of DOM. Root can be either an object or array. - - assert(json.HasMember("hello")); - assert(json["hello"].IsString()); - printf("hello = %s\n", json["hello"].GetString()); - - // Since version 0.2, you can use single lookup to check the existing of member and its value: - rapidjson::Value::MemberIterator hello = json.FindMember("hello"); - assert(hello != json.MemberEnd()); - assert(hello->value.IsString()); - assert(strcmp("world", hello->value.GetString()) == 0); - (void)hello; - - assert(json["t"].IsBool()); // JSON true/false are bool. Can also uses more specific function IsTrue(). - printf("t = %s\n", json["t"].GetBool() ? "true" : "false"); - - assert(json["f"].IsBool()); - printf("f = %s\n", json["f"].GetBool() ? "true" : "false"); - - printf("n = %s\n", json["n"].IsNull() ? "null" : "?"); - - assert(json["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type. - assert(json["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true. - printf("i = %d\n", json["i"].GetInt()); // Alternative (int)document["i"] - - assert(json["pi"].IsNumber()); - assert(json["pi"].IsDouble()); - printf("pi = %g\n", json["pi"].GetDouble()); - - { - const rapidjson::Value& a = json["a"]; // Using a reference for consecutive access is handy and faster. - assert(a.IsArray()); - for (rapidjson::SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t. - printf("a[%d] = %d\n", i, a[i].GetInt()); - - int y = a[0].GetInt(); - (void)y; - - // Iterating array with iterators - printf("a = "); - for (rapidjson::Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) - printf("%d ", itr->GetInt()); - printf("\n"); - } - - // Iterating object members - static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; - for (rapidjson::Value::ConstMemberIterator itr = json.MemberBegin(); itr != json.MemberEnd(); ++itr) - printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]); - - - + // Iterating object members + static const char* kTypeNames[] = { "Null", "False", "True", "Object", + "Array", "String", "Number" }; + for (rapidjson::Value::ConstMemberIterator itr = json.MemberBegin(); + itr != json.MemberEnd(); ++itr) + printf("Type of member %s is %s\n", itr->name.GetString(), + kTypeNames[itr->value.GetType()]); +*/ return 0; } std::string Switch::toString() { - //////////////////////////////////////////////////////////////////////////// - // 3. Modify values in document. - // Change i to a bigger number - { - uint64_t f20 = 1; // compute factorial of 20 - for (uint64_t j = 1; j <= 20; j++) - f20 *= j; - json["i"] = f20; // Alternate form: document["i"].SetUint64(f20) - assert(!json["i"].IsInt()); // No longer can be cast as int or uint. - } + if (!json.IsObject()) { + json.SetObject(); + } + rapidjson::Document::AllocatorType& allocator = json.GetAllocator(); - // Adding values to array. - { - rapidjson::Value& a = json["a"]; // This time we uses non-const reference. - rapidjson::Document::AllocatorType& allocator = json.GetAllocator(); - for (int i = 5; i <= 10; i++) - a.PushBack(i, allocator); // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's. + json.AddMember("hostname", jsonNode(settings.hostname, json), allocator); + json.AddMember("ip", jsonNode(settings.ip_addr, json), allocator); + json.AddMember("netmask", jsonNode(settings.ip_mask, json), allocator); + json.AddMember("gateway", jsonNode(settings.gateway, json), allocator); + json.AddMember("type", jsonNode(device.type, json), allocator); + json.AddMember("hardware_version", jsonNode(device.hardware_version, json), + allocator); + json.AddMember("firmware_version", jsonNode(device.firmware_version, json), + allocator); + json.AddMember("ports", jsonNode(ports, json), allocator); + json.AddMember("vlans", jsonNode(vlans, json), allocator); - // Fluent API - a.PushBack("Lua", allocator).PushBack("Mio", allocator); - } - - // Making string values. - - // This version of SetString() just store the pointer to the string. - // So it is for literal and string that exists within value's life-cycle. - { - json["hello"] = "hostname"; //settings.hostname; // This will invoke strlen() - // Faster version: - // document["hello"].SetString("rapidjson", 9); - } - - // This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer. - rapidjson::Value author; - { - char buffer[10]; - int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string. - - author.SetString(buffer, static_cast(len), json.GetAllocator()); - // Shorter but slower version: - // document["hello"].SetString(buffer, document.GetAllocator()); - - // Constructor version: - // Value author(buffer, len, document.GetAllocator()); - // Value author(buffer, document.GetAllocator()); - memset(buffer, 0, sizeof(buffer)); // For demonstration purpose. - } - // Variable 'buffer' is unusable now but 'author' has already made a copy. - json.AddMember("author", author, json.GetAllocator()); - - assert(author.IsNull()); // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null. - - - - - - - - - - - - - - - - std::cout<<"\nModified JSON with reformatting:\n"; - rapidjson::StringBuffer sb; - rapidjson::PrettyWriter writer(sb); - json.Accept(writer); // Accept() traverses the DOM and generates Handler events. - return sb.GetString(); + rapidjson::StringBuffer sb; + rapidjson::PrettyWriter writer(sb); + json.Accept(writer); + return sb.GetString(); } - diff --git a/src/Switch.h b/src/Switch.h index 5a7ede2..44b715c 100644 --- a/src/Switch.h +++ b/src/Switch.h @@ -17,44 +17,17 @@ #define DEFAULT_USER "admin" #define DEFAULT_PASS "admin" -typedef rapidjson::Value jsonNode; - -/* -template -jsonNode to_json(const T &x) { - // TODO Throw undefined - return NULL; -} - -template<> jsonNode to_json(const vlan &x) { - jsonNode ret; - return ret; -} - -template -T from_json(const jsonNode &s) { -// TODO Throw not implemented - return NULL; -} - -template<> vlan from_json(const jsonNode &s) { - vlan ret; - return ret; -}*/ - struct vlan { int vlan_id; std::string name; + std::vector tagged_member; + std::vector untagged_member; }; struct port { byte id; byte status; - struct { - std::vector tagged; - std::vector untagged; - int pvid; - } vlan; + int pvid; }; class Switch {