json parser

This commit is contained in:
/jdi/ 2015-10-17 19:43:21 +02:00
parent b1c5a3af6e
commit 3aa3cee61c
7 changed files with 114 additions and 204 deletions

View file

@ -25,14 +25,15 @@
-u --user <[password:]username>\n\ -u --user <[password:]username>\n\
-p --password <password>\n\ -p --password <password>\n\
Login with Username and Password\n\ Login with Username and Password\n\
-f --file <path> Not yet implemented:.choose a settings file\n\ -f --file <path> choose a settings file\n\
-t --timeout <n> Not yet implemented\n\ -t --timeout <n> Not yet implemented\n\
-w --wait Not yet implemented: blocking until operation is completed\n\ -w --wait Not yet implemented: blocking until operation is completed\n\
-s --permanent Not yet implemented: make changes immediately permanent\n\n\ -s --permanent Not yet implemented: make changes immediately permanent\n\n\
Command Summary:\n\ Command Summary:\n\
help This help text\n\ help This help text\n\
list list all connected switches\n\ list list all connected switches\n\
sniff capture and display all incoming or outgoing packets\n\ sniff [type:<type>] [<filter>]\n\
capture and display all incoming or outgoing packets\n\
depending on the --reverse option\n\ depending on the --reverse option\n\
encode use encoding algorithm on hex data separated by colon\n\ encode use encoding algorithm on hex data separated by colon\n\
get Not yet implemented\n\ get Not yet implemented\n\

View file

@ -143,8 +143,10 @@ std::string Packet::opCodeToString() {
return "GET"; return "GET";
case SET: case SET:
return "SET"; return "SET";
case RECEIVE: case LOGIN:
return "RECEIVE"; return "LOGIN";
case RETURN:
return "RETURN";
case READ5: case READ5:
return "READ5"; return "READ5";
default: default:

View file

@ -16,7 +16,7 @@
class Packet { class Packet {
public: public:
enum OpCode { enum OpCode {
DISCOVERY, GET, SET, READ4,RECEIVE, READ5 DISCOVERY, GET, SET, LOGIN, RETURN, READ5
}; };
Packet(OpCode); Packet(OpCode);
void encode(bytes&); void encode(bytes&);

View file

@ -9,6 +9,7 @@
#include "Options.h" #include "Options.h"
#include "Program.h" #include "Program.h"
#include "File.h"
#include "Host.h" #include "Host.h"
#include "Socket.h" #include "Socket.h"
#include "Switch.h" #include "Switch.h"
@ -45,6 +46,8 @@ int Program::list() {
datasets d =a.getPayload(); datasets d =a.getPayload();
Switch s = Switch(); Switch s = Switch();
s.parse(d); s.parse(d);
File f;
f.write("config.json", s.toString());
std::cout <<"Devices:\n\t"<<s.settings.hostname<<" ("<< s.device.type<<")\tMAC: "<<s.device.mac<<"\tIP: "<<s.settings.ip_addr<<"\n"; std::cout <<"Devices:\n\t"<<s.settings.hostname<<" ("<< s.device.type<<")\tMAC: "<<s.device.mac<<"\tIP: "<<s.settings.ip_addr<<"\n";
} }
return 1; return 1;
@ -83,7 +86,7 @@ int Program::sniff() {
auto lookup=(options.flags & FLAG_REVERSE)?snd_lookup:rcv_lookup; auto lookup=(options.flags & FLAG_REVERSE)?snd_lookup:rcv_lookup;
if(lookup.exists(d.type)) { if(lookup.exists(d.type)) {
if(d.len>0) { if(d.len>0) {
std::cout<<std::dec<<"\t++"<<std::hex<<d.type<<std::dec<<"++\n"; std::cout<<std::dec<<"\t++"<<std::hex<<d.type<<"++ :"<<d.value<<std::dec<<"\n";
} else { } else {
std::cout<<std::dec<<"#"<<d.type<<"\tLength: "<<d.len<<"\n"; std::cout<<std::dec<<"#"<<d.type<<"\tLength: "<<d.len<<"\n";
std::cout<<std::hex<< "\tHex: " <<d.value<<"\n"; std::cout<<std::hex<< "\tHex: " <<d.value<<"\n";
@ -163,19 +166,16 @@ int Program::getProperty() {
} }
int Program::save() { int Program::save() {
Switch sw = Switch(); Switch sw = Switch();
std::string str = sw.toString(); sw.settings.hostname = "testname.lan";
//File = fopen(otions.file) File f;
f.write("config.json", sw.toString());
return 0; return 1;
} }
int Program::restore() { int Program::restore() {
File f;
const char str[] = Switch sw;
" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; sw.parse(f.read("config.json"));
printf("Original JSON:\n %s\n", str); std::cout <<"Devices:\n\t"<<sw.settings.hostname<<" ("<< sw.device.type<<")\tMAC: "<<sw.device.mac<<"\tIP: "<<sw.settings.ip_addr<<"\n";
Switch sw = Switch();
sw.parse(str);
//File = fopen(otions.file)
return 1; return 1;
} }
int Program::flash() { int Program::flash() {

View file

@ -4,9 +4,6 @@
* Created on: 02.09.2015 * Created on: 02.09.2015
* Author: jdi * Author: jdi
*/ */
//#include <cstdio>
//#include <cerrno>
//#include <cstring>
#include <cstdlib> #include <cstdlib>
#include <array> #include <array>
#include <unistd.h> #include <unistd.h>
@ -75,7 +72,7 @@ void Socket::listen() {
listen(); listen();
} else { } else {
data.resize(bytes_recvd); data.resize(bytes_recvd);
Packet p = Packet(Packet::RECEIVE); Packet p = Packet(Packet::RETURN);
p.encode(data); p.encode(data);
p.parse(data); p.parse(data);
datasets l = p.getPayload(); datasets l = p.getPayload();

View file

@ -9,6 +9,7 @@
#include "Types.h" #include "Types.h"
#include "Switch.h" #include "Switch.h"
#include "Lookup.h" #include "Lookup.h"
#include "jsonNode.h"
#include "Options.h" #include "Options.h"
int Switch::parse(datasets arr) { int Switch::parse(datasets arr) {
@ -57,40 +58,25 @@ int Switch::parse(std::string str) {
if (options.flags & FLAG_DEBUG) 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);
*/
////////////////////////////////////////////////////////////////////////////
// 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: // 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"); rapidjson::Value::MemberIterator hello = json.FindMember("hello");
assert(hello != json.MemberEnd()); assert(hello != json.MemberEnd());
assert(hello->value.IsString()); assert(hello->value.IsString());
@ -124,94 +110,45 @@ int Switch::parse(std::string str) {
// Iterating array with iterators // Iterating array with iterators
printf("a = "); printf("a = ");
for (rapidjson::Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) for (rapidjson::Value::ConstValueIterator itr = a.Begin();
itr != a.End(); ++itr)
printf("%d ", itr->GetInt()); printf("%d ", itr->GetInt());
printf("\n"); printf("\n");
} }
// Iterating object members // Iterating object members
static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; static const char* kTypeNames[] = { "Null", "False", "True", "Object",
for (rapidjson::Value::ConstMemberIterator itr = json.MemberBegin(); itr != json.MemberEnd(); ++itr) "Array", "String", "Number" };
printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]); 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; return 0;
} }
std::string Switch::toString() { std::string Switch::toString() {
////////////////////////////////////////////////////////////////////////////
// 3. Modify values in document.
// Change i to a bigger number if (!json.IsObject()) {
{ json.SetObject();
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.
} }
// Adding values to array.
{
rapidjson::Value& a = json["a"]; // This time we uses non-const reference.
rapidjson::Document::AllocatorType& allocator = json.GetAllocator(); 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.
// Fluent API json.AddMember("hostname", jsonNode(settings.hostname, json), allocator);
a.PushBack("Lua", allocator).PushBack("Mio", 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);
// 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<size_t>(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::StringBuffer sb;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb); rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
json.Accept(writer); // Accept() traverses the DOM and generates Handler events. json.Accept(writer);
return sb.GetString(); return sb.GetString();
} }

View file

@ -17,44 +17,17 @@
#define DEFAULT_USER "admin" #define DEFAULT_USER "admin"
#define DEFAULT_PASS "admin" #define DEFAULT_PASS "admin"
typedef rapidjson::Value jsonNode;
/*
template<typename T>
jsonNode to_json(const T &x) {
// TODO Throw undefined
return NULL;
}
template<> jsonNode to_json<vlan>(const vlan &x) {
jsonNode ret;
return ret;
}
template<typename T>
T from_json(const jsonNode &s) {
// TODO Throw not implemented
return NULL;
}
template<> vlan from_json<vlan>(const jsonNode &s) {
vlan ret;
return ret;
}*/
struct vlan { struct vlan {
int vlan_id; int vlan_id;
std::string name; std::string name;
std::vector<byte> tagged_member;
std::vector<byte> untagged_member;
}; };
struct port { struct port {
byte id; byte id;
byte status; byte status;
struct {
std::vector<vlan*> tagged;
std::vector<vlan*> untagged;
int pvid; int pvid;
} vlan;
}; };
class Switch { class Switch {