json parser
This commit is contained in:
parent
b1c5a3af6e
commit
3aa3cee61c
7 changed files with 114 additions and 204 deletions
|
@ -25,23 +25,24 @@
|
||||||
-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\
|
||||||
depending on the --reverse option\n\
|
capture and display all incoming or outgoing packets\n\
|
||||||
encode use encoding algorithm on hex data separated by colon\n\
|
depending on the --reverse option\n\
|
||||||
get Not yet implemented\n\
|
encode use encoding algorithm on hex data separated by colon\n\
|
||||||
set Not yet implemented\n\
|
get Not yet implemented\n\
|
||||||
save Not yet implemented: save config to file\n\
|
set Not yet implemented\n\
|
||||||
restore Not yet implemented: restore onfig from file\n\
|
save Not yet implemented: save config to file\n\
|
||||||
flash Not yet implemented: replace firmware\n\
|
restore Not yet implemented: restore onfig from file\n\
|
||||||
reboot Not yet implemented\n\
|
flash Not yet implemented: replace firmware\n\
|
||||||
reset Not yet implemented\n\n\
|
reboot Not yet implemented\n\
|
||||||
|
reset Not yet implemented\n\n\
|
||||||
### for questions please contact <smrtlink@jdi.li> ###\n\n"
|
### for questions please contact <smrtlink@jdi.li> ###\n\n"
|
||||||
|
|
||||||
#define FLAG_HEX 1
|
#define FLAG_HEX 1
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
221
src/Switch.cpp
221
src/Switch.cpp
|
@ -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) {
|
||||||
|
@ -52,166 +53,102 @@ int Switch::parse(dataset d) {
|
||||||
|
|
||||||
int Switch::parse(std::string str) {
|
int Switch::parse(std::string str) {
|
||||||
|
|
||||||
if (json.Parse(str.c_str()).HasParseError())
|
if (json.Parse(str.c_str()).HasParseError())
|
||||||
return 1;
|
return 1;
|
||||||
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// 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()]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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()]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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++)
|
rapidjson::Document::AllocatorType& allocator = json.GetAllocator();
|
||||||
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.
|
json.AddMember("hostname", jsonNode(settings.hostname, json), allocator);
|
||||||
{
|
json.AddMember("ip", jsonNode(settings.ip_addr, json), allocator);
|
||||||
rapidjson::Value& a = json["a"]; // This time we uses non-const reference.
|
json.AddMember("netmask", jsonNode(settings.ip_mask, json), allocator);
|
||||||
rapidjson::Document::AllocatorType& allocator = json.GetAllocator();
|
json.AddMember("gateway", jsonNode(settings.gateway, json), allocator);
|
||||||
for (int i = 5; i <= 10; i++)
|
json.AddMember("type", jsonNode(device.type, json), allocator);
|
||||||
a.PushBack(i, allocator); // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.
|
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
|
rapidjson::StringBuffer sb;
|
||||||
a.PushBack("Lua", allocator).PushBack("Mio", allocator);
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
|
||||||
}
|
json.Accept(writer);
|
||||||
|
return sb.GetString();
|
||||||
// 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::PrettyWriter<rapidjson::StringBuffer> writer(sb);
|
|
||||||
json.Accept(writer); // Accept() traverses the DOM and generates Handler events.
|
|
||||||
return sb.GetString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
33
src/Switch.h
33
src/Switch.h
|
@ -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 {
|
int pvid;
|
||||||
std::vector<vlan*> tagged;
|
|
||||||
std::vector<vlan*> untagged;
|
|
||||||
int pvid;
|
|
||||||
} vlan;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Switch {
|
class Switch {
|
||||||
|
|
Loading…
Reference in a new issue