mirror of
https://github.com/GOSTSec/poolserver
synced 2025-01-30 00:14:17 +00:00
JSON Parser n smth more
This commit is contained in:
parent
ff224b7955
commit
8dca8f0932
@ -34,6 +34,7 @@ bool InitConfig(int argc, char *argv[])
|
||||
// Server
|
||||
descServer.add_options()
|
||||
("MinDiffTime", boost::program_options::value<uint32_t>()->default_value(100), "Minimum server diff time")
|
||||
("MiningAddress", boost::program_options::value<std::string>()->default_value("n1w8gkPXdNGb6edm4vujBn71A72eQFCNCw"), "Address to send coins to")
|
||||
;
|
||||
|
||||
// Stratum
|
||||
|
@ -35,6 +35,9 @@ int Server::Run()
|
||||
|
||||
//InitDatabase();
|
||||
|
||||
JSON node = JSON::FromString("{\"test\":{\"omg\":\"smth\"},\"other\":\"smth2\"}");
|
||||
sLog.Info(LOG_SERVER, "Something: %s", node.ToString().c_str());
|
||||
|
||||
/*std::vector<byte> test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(Crypto::SHA256D(test)).c_str());
|
||||
sLog.Info(LOG_SERVER, "RevHash: %s", Util::BinToASCII(Crypto::SHA256D(Util::Reverse(test))).c_str());
|
||||
|
@ -3,52 +3,84 @@
|
||||
|
||||
namespace Stratum
|
||||
{
|
||||
void Client::SendJob(bool clean)
|
||||
{
|
||||
if (clean)
|
||||
_jobs.clear();
|
||||
|
||||
Job job = GetJob();
|
||||
uint64 jobid = _jobid++;
|
||||
|
||||
_jobs[jobid] = job;
|
||||
|
||||
// Coinbase parts
|
||||
ByteBuffer coinbasebuf;
|
||||
coinbasebuf << job.block->tx[0];
|
||||
BinaryData coinbase = coinbasebuf.Binary();
|
||||
// tx.version + tx.in[0].outpoint.hash + tx.in[0].outpoint.n + tx.script (block height)
|
||||
uint32 cbsplit = 4 + 32 + 4 + 4;
|
||||
BinaryData coinbase1 = BinaryData(coinbase.begin(), coinbase.begin() + cbsplit);
|
||||
BinaryData coinbase2 = BinaryData(coinbase.begin() + cbsplit + 8, coinbase.end()); // plus extranonce size
|
||||
|
||||
// Build merkle branch array
|
||||
JSON merkle_branch(JSON_ARRAY);
|
||||
uint64 branches = job.block->merkleBranches;
|
||||
uint64 index = 0;
|
||||
while (branches > 1) {
|
||||
merkle_branch.Add(Util::BinToASCII(job.block->merkleTree[index+1]));
|
||||
index += branches;
|
||||
branches /= 2;
|
||||
}
|
||||
|
||||
JSON params;
|
||||
params.Add("bf");
|
||||
params.Add(Util::BinToASCII(Util::Reverse(job.block->prevBlockHash)));
|
||||
params.Add(Util::BinToASCII(coinbase1));
|
||||
params.Add(Util::BinToASCII(coinbase2));
|
||||
params.Add(merkle_branch);
|
||||
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->version).Binary())));
|
||||
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->bits).Binary())));
|
||||
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->time).Binary())));
|
||||
params.Add(clean);
|
||||
|
||||
JSON msg;
|
||||
msg["params"] = params;
|
||||
msg["id"];
|
||||
msg["method"] = "mining.notify";
|
||||
|
||||
SendMessage(msg);
|
||||
}
|
||||
|
||||
void Client::OnMiningSubscribe(JSON msg)
|
||||
{
|
||||
_subscribed = true;
|
||||
_extranonce = _server->GetExtranonce();
|
||||
|
||||
Job job = GetJob();
|
||||
_jobs.push_back(job);
|
||||
|
||||
JSON response;
|
||||
response.Set("id", msg["id"].Get<uint32>());
|
||||
response.Set("error", NULL);
|
||||
|
||||
JSON miningdiff;
|
||||
miningdiff.Add("mining.set_difficulty");
|
||||
JSON lala;
|
||||
lala.Set("", 1);
|
||||
miningdiff.Add(lala);
|
||||
|
||||
JSON notify;
|
||||
notify.Add("mining.notify");
|
||||
notify.Add("abc");
|
||||
|
||||
JSON something;
|
||||
something.Add(miningdiff);
|
||||
something.Add(notify);
|
||||
notify.Add("ae6812eb4cd7735a302a8a9dd95cf71f");
|
||||
|
||||
JSON result;
|
||||
result.Add(something);
|
||||
result.Add(notify);
|
||||
ByteBuffer noncebuf;
|
||||
noncebuf << _extranonce;
|
||||
JSON omg;
|
||||
omg.Set("", Util::BinToASCII(noncebuf.Binary()));
|
||||
result.Add(omg);
|
||||
JSON shit;
|
||||
shit.Set("", 4);
|
||||
result.Add(shit);
|
||||
result.Add(Util::BinToASCII(noncebuf.Binary()));
|
||||
result.Add(int64(4));
|
||||
|
||||
response.Set("result", result);
|
||||
JSON response;
|
||||
response["id"] = msg["id"].GetInt();
|
||||
response["result"] = result;
|
||||
response["error"];
|
||||
|
||||
SendMessage(response);
|
||||
|
||||
SendJob(false);
|
||||
}
|
||||
|
||||
Job Client::GetJob()
|
||||
{
|
||||
Job job;
|
||||
job.work = _server->GetWork();
|
||||
job.block = _server->GetWork();
|
||||
return job;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace Stratum
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
Client(Server* server, asio::io_service& io_service) : _server(server), _socket(io_service), _subscribed(false)
|
||||
Client(Server* server, asio::io_service& io_service) : _server(server), _socket(io_service), _subscribed(false), _jobid(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -40,13 +40,12 @@ namespace Stratum
|
||||
boost::bind(&Client::_OnReceive, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void SendJob()
|
||||
{
|
||||
}
|
||||
void SendJob(bool clean);
|
||||
|
||||
void SendMessage(JSON msg)
|
||||
{
|
||||
std::string data = msg.ToString();
|
||||
data += '\n';
|
||||
sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str());
|
||||
_socket.send(boost::asio::buffer(data.c_str(), data.length()));
|
||||
}
|
||||
@ -55,17 +54,17 @@ namespace Stratum
|
||||
|
||||
void OnMiningAuthorize(JSON msg)
|
||||
{
|
||||
std::string username = msg["result"][0].Get<std::string>();
|
||||
std::string username = msg["result"][0].GetString();
|
||||
JSON response;
|
||||
response.Set("id", msg["id"].Get<uint32>());
|
||||
response.Set("error", NULL);
|
||||
response.Set("result", true);
|
||||
response["id"] = msg["id"].GetInt();
|
||||
response["error"];
|
||||
response["result"] = true;
|
||||
SendMessage(response);
|
||||
}
|
||||
|
||||
void OnMessage(JSON msg)
|
||||
{
|
||||
std::string method = msg["method"].Get<std::string>();
|
||||
std::string method = msg["method"].GetString();
|
||||
sLog.Debug(LOG_SERVER, "Method: %s", method.c_str());
|
||||
|
||||
if (method.compare("mining.subscribe") == 0)
|
||||
@ -100,7 +99,8 @@ namespace Stratum
|
||||
// Jobs
|
||||
bool _subscribed;
|
||||
uint32 _extranonce;
|
||||
std::vector<Job> _jobs;
|
||||
std::map<uint64, Job> _jobs;
|
||||
uint64 _jobid;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Stratum
|
||||
class Job
|
||||
{
|
||||
public:
|
||||
Bitcoin::BlockPtr work;
|
||||
Bitcoin::BlockPtr block;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ namespace Stratum
|
||||
public:
|
||||
Server(asio::io_service& io_service) : _io_service(io_service), _acceptor(io_service), _blockCheckTimer(io_service), _blockHeight(0), _extranonce(0)
|
||||
{
|
||||
_pubkey = Util::ASCIIToBin(sConfig.Get<std::string>("MiningAddress"));
|
||||
}
|
||||
|
||||
~Server()
|
||||
@ -104,20 +105,20 @@ namespace Stratum
|
||||
|
||||
Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block());
|
||||
|
||||
block->version = response["version"].Get<uint32>();;
|
||||
block->prevBlockHash = Util::ASCIIToBin(response["previousblockhash"].Get<std::string>());
|
||||
|
||||
block->version = response["version"].GetInt();
|
||||
block->prevBlockHash = Util::ASCIIToBin(response["previousblockhash"].GetString());
|
||||
block->time = response["curtime"].GetInt();
|
||||
// Set bits
|
||||
ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].Get<std::string>()));
|
||||
ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].GetString()));
|
||||
bitbuf >> block->bits;
|
||||
|
||||
// Add coinbase tx
|
||||
block->tx.push_back(CreateCoinbaseTX(_blockHeight, _pubkey, response["coinbasevalue"].Get<int64>()));
|
||||
block->tx.push_back(CreateCoinbaseTX(_blockHeight, _pubkey, response["coinbasevalue"].GetInt()));
|
||||
|
||||
// Add other transactions
|
||||
JSON trans = response["transactions"];
|
||||
for (uint64 i = 0; i < trans.Size(); ++i) {
|
||||
ByteBuffer txbuf(Util::ASCIIToBin(trans[i]["data"].Get<std::string>()));
|
||||
ByteBuffer txbuf(Util::ASCIIToBin(trans[i]["data"].GetString()));
|
||||
Bitcoin::Transaction tx;
|
||||
txbuf >> tx;
|
||||
block->tx.push_back(tx);
|
||||
@ -135,7 +136,7 @@ namespace Stratum
|
||||
sLog.Debug(LOG_STRATUM, "Checking for new blocks...");
|
||||
|
||||
JSON response = _bitcoinrpc->Query("getinfo");
|
||||
uint32 curBlock = response["blocks"].Get<uint32>();
|
||||
uint32 curBlock = response["blocks"].GetInt();
|
||||
|
||||
if (curBlock > _blockHeight) {
|
||||
sLog.Debug(LOG_STRATUM, "New block on network! Height: %u", curBlock);
|
||||
@ -149,8 +150,10 @@ namespace Stratum
|
||||
|
||||
Bitcoin::Transaction CreateCoinbaseTX(uint32 blockHeight, BinaryData pubkey, int64 value)
|
||||
{
|
||||
// Extranonce placeholder
|
||||
BinaryData extranonce_ph(8, 0);
|
||||
ByteBuffer scriptsig;
|
||||
scriptsig << _blockHeight;
|
||||
scriptsig << _blockHeight << extranonce_ph;
|
||||
|
||||
Bitcoin::OutPoint outpoint;
|
||||
outpoint.hash.resize(32, 0);
|
||||
|
@ -28,6 +28,7 @@ namespace Bitcoin
|
||||
|
||||
// Other data
|
||||
std::vector<BinaryData> merkleTree;
|
||||
uint64 merkleBranches;
|
||||
|
||||
void BuildMerkleTree()
|
||||
{
|
||||
@ -40,6 +41,9 @@ namespace Bitcoin
|
||||
++levels;
|
||||
}
|
||||
|
||||
// Used when sending merkle branches
|
||||
merkleBranches = branches;
|
||||
|
||||
// Add transactions
|
||||
for (uint64 i = 0; i < branches; ++i)
|
||||
merkleTree.push_back(tx[std::min(i, tx.size()-1)].GetHash());
|
||||
|
@ -8,6 +8,13 @@ class ByteBuffer
|
||||
{
|
||||
public:
|
||||
ByteBuffer(): pointer(0) {}
|
||||
|
||||
template<typename T>
|
||||
ByteBuffer(T data): pointer(0)
|
||||
{
|
||||
Append<T>(data);
|
||||
}
|
||||
|
||||
ByteBuffer(BinaryData data): pointer(0), vec(data) {}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& b)
|
||||
|
@ -1,22 +1,109 @@
|
||||
#include "JSON.h"
|
||||
#include "JSONReader.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "Log.h"
|
||||
|
||||
JSON JSON::FromString(std::string jsonstring)
|
||||
{
|
||||
JSON json;
|
||||
json.pt = new boost::property_tree::ptree();
|
||||
std::stringstream ss;
|
||||
ss.str(jsonstring);
|
||||
boost::property_tree::json_parser::read_json(ss, *json.pt);
|
||||
return json;
|
||||
JSON node;
|
||||
JSONReader::Parse(jsonstring, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
std::string JSON::ToString()
|
||||
{
|
||||
std::stringstream ss;
|
||||
boost::property_tree::json_parser::write_json(ss, *pt);
|
||||
return ss.str();
|
||||
Write(ss);
|
||||
std::string json = ss.str();
|
||||
|
||||
// If it's array we have to wrap json into {}
|
||||
if (json[0] == '[')
|
||||
return "{" + json + "}";
|
||||
else
|
||||
return json;
|
||||
}
|
||||
|
||||
void JSON::Write(std::stringstream& ss)
|
||||
{
|
||||
switch (_type)
|
||||
{
|
||||
case JSON_NULL:
|
||||
ss << "null";
|
||||
break;
|
||||
case JSON_BOOL:
|
||||
if (GetBool())
|
||||
ss << "true";
|
||||
else
|
||||
ss << "false";
|
||||
break;
|
||||
case JSON_INTEGER:
|
||||
ss << GetInt();
|
||||
break;
|
||||
case JSON_DOUBLE:
|
||||
ss << GetDouble();
|
||||
break;
|
||||
case JSON_STRING:
|
||||
ss << '"' << EscapeString(GetString()) << '"';
|
||||
break;
|
||||
case JSON_ARRAY:
|
||||
{
|
||||
ss << '[';
|
||||
for (uint32 i = 0; i < _vec.size(); ++i)
|
||||
{
|
||||
if (i)
|
||||
ss << ", ";
|
||||
_vec[i].Write(ss);
|
||||
}
|
||||
ss << ']';
|
||||
break;
|
||||
}
|
||||
case JSON_OBJECT:
|
||||
{
|
||||
ss << '{';
|
||||
for (uint64 i = 0; i < _mapOrder.size(); ++i)
|
||||
{
|
||||
if (i)
|
||||
ss << ',';
|
||||
std::string key = _mapOrder[i];
|
||||
ss << '"' << key << "\":";
|
||||
_map[key].Write(ss);
|
||||
}
|
||||
ss << '}';
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw "Unknown type";
|
||||
}
|
||||
}
|
||||
|
||||
std::string JSON::EscapeString(std::string str)
|
||||
{
|
||||
static std::map<char, std::string> escapes = boost::assign::map_list_of
|
||||
('"', "\\\"")
|
||||
('\'', "\\'");
|
||||
/*('\\', "\\\\")
|
||||
('/', "\\/")
|
||||
('b', "\\b")
|
||||
('f', "\\f")
|
||||
('n', "\\n")
|
||||
('r', "\\r")
|
||||
('t', "\\t")
|
||||
('u', "\\u");*/
|
||||
|
||||
for (uint32 i = 0; i < str.length(); ++i)
|
||||
{
|
||||
if (escapes.count(str[i])) {
|
||||
std::string esc = escapes[str[i]];
|
||||
str.replace(i, 1, esc.c_str(), esc.length());
|
||||
i += esc.length()-1;
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
@ -4,85 +4,235 @@
|
||||
#include "Common.h"
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <Log.h>
|
||||
|
||||
enum JSONValueType
|
||||
{
|
||||
JSON_NULL = 0,
|
||||
JSON_ARRAY = 1,
|
||||
JSON_OBJECT = 2,
|
||||
JSON_BOOL = 3,
|
||||
JSON_INTEGER = 4,
|
||||
JSON_DOUBLE = 5,
|
||||
JSON_STRING = 6
|
||||
};
|
||||
|
||||
typedef boost::variant<bool, int64, double, std::string> JSONValue;
|
||||
|
||||
class JSON
|
||||
{
|
||||
public:
|
||||
static JSON FromString(std::string jsonstring);
|
||||
|
||||
JSON(bool base = true) : _base(base), pt(NULL)
|
||||
JSON(JSONValueType type = JSON_NULL) : _type(type)
|
||||
{
|
||||
if (base)
|
||||
pt = new boost::property_tree::ptree();
|
||||
}
|
||||
|
||||
~JSON()
|
||||
{
|
||||
//if (_base && pt)
|
||||
// delete pt;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T Get()
|
||||
// Arrays
|
||||
JSON& operator[] (uint32 index)
|
||||
{
|
||||
return pt->get_value<T>();
|
||||
return _vec[index];
|
||||
}
|
||||
|
||||
JSON operator[] (std::string key)
|
||||
template<typename T>
|
||||
void Add(T val)
|
||||
{
|
||||
JSON json(false);
|
||||
json.pt = &pt->get_child(key);
|
||||
return json;
|
||||
if (_type != JSON_ARRAY) {
|
||||
if (_type != JSON_NULL)
|
||||
throw "Bad type";
|
||||
else
|
||||
_type = JSON_ARRAY;
|
||||
}
|
||||
|
||||
JSON node;
|
||||
node = val;
|
||||
_vec.push_back(node);
|
||||
}
|
||||
|
||||
JSON operator[] (uint32 index)
|
||||
void AddNull()
|
||||
{
|
||||
JSON json(false);
|
||||
boost::property_tree::ptree::iterator it = pt->begin();
|
||||
for (int i = 0; i < index; ++i)
|
||||
++it;
|
||||
boost::property_tree::ptree::value_type& kv = *it;
|
||||
json.pt = &kv.second;
|
||||
return json;
|
||||
if (_type != JSON_ARRAY) {
|
||||
if (_type != JSON_NULL)
|
||||
throw "Bad type";
|
||||
else
|
||||
_type = JSON_ARRAY;
|
||||
}
|
||||
|
||||
JSON node;
|
||||
_vec.push_back(node);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Set(std::string key, T value)
|
||||
// Objects
|
||||
JSON& operator[] (std::string key)
|
||||
{
|
||||
pt->put<T>(key, value);
|
||||
if (_type != JSON_OBJECT) {
|
||||
if (_type != JSON_NULL)
|
||||
throw "Bad type";
|
||||
else
|
||||
_type = JSON_OBJECT;
|
||||
}
|
||||
|
||||
// Keep insertion order
|
||||
if (!_map.count(key))
|
||||
_mapOrder.push_back(key);
|
||||
|
||||
// std::map[] automatically creates key if it does not exist
|
||||
return _map[key];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Add(T value)
|
||||
template<typename T>
|
||||
void Set(std::string key, T val)
|
||||
{
|
||||
pt->push_back(std::make_pair("", value));
|
||||
if (_type != JSON_OBJECT) {
|
||||
if (_type != JSON_NULL)
|
||||
throw "Bad type";
|
||||
else
|
||||
_type = JSON_OBJECT;
|
||||
}
|
||||
|
||||
// Keep insertion order
|
||||
if (!_map.count(key))
|
||||
_mapOrder.push_back(key);
|
||||
|
||||
// std::map[] automatically creates key if it does not exist
|
||||
_map[key] = val;
|
||||
}
|
||||
|
||||
uint64_t Size()
|
||||
// Primitive types
|
||||
bool GetBool()
|
||||
{
|
||||
return pt->size();
|
||||
if (_type != JSON_BOOL)
|
||||
throw "Bad type";
|
||||
|
||||
return boost::get<bool>(_val);
|
||||
}
|
||||
|
||||
void operator= (bool val)
|
||||
{
|
||||
_type = JSON_BOOL;
|
||||
_val = val;
|
||||
}
|
||||
|
||||
int64 GetInt()
|
||||
{
|
||||
if (_type != JSON_INTEGER)
|
||||
throw "Bad type";
|
||||
|
||||
return boost::get<int64>(_val);
|
||||
}
|
||||
|
||||
void operator= (int64 val)
|
||||
{
|
||||
_type = JSON_INTEGER;
|
||||
_val = val;
|
||||
}
|
||||
|
||||
double GetDouble()
|
||||
{
|
||||
if (_type != JSON_DOUBLE)
|
||||
throw "Bad type";
|
||||
|
||||
return boost::get<double>(_val);
|
||||
}
|
||||
|
||||
void operator= (double val)
|
||||
{
|
||||
_type = JSON_DOUBLE;
|
||||
_val = val;
|
||||
}
|
||||
|
||||
std::string GetString()
|
||||
{
|
||||
if (_type != JSON_STRING)
|
||||
throw "Bad type";
|
||||
|
||||
return boost::get<std::string>(_val);
|
||||
}
|
||||
|
||||
void operator= (std::string val)
|
||||
{
|
||||
_type = JSON_STRING;
|
||||
_val = val;
|
||||
}
|
||||
|
||||
// Fix for static strings
|
||||
void operator= (const char* val)
|
||||
{
|
||||
_type = JSON_STRING;
|
||||
_val = std::string(val);
|
||||
}
|
||||
|
||||
// Generic function
|
||||
bool Empty()
|
||||
{
|
||||
if (_type == JSON_NULL)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 Size()
|
||||
{
|
||||
if (_type == JSON_ARRAY)
|
||||
return _vec.size();
|
||||
else if (_type == JSON_OBJECT)
|
||||
return _map.size();
|
||||
else
|
||||
throw "Type has no size";
|
||||
}
|
||||
|
||||
JSONValueType GetType()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
void SetType(JSONValueType type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
// Used for writting
|
||||
std::string EscapeString(std::string);
|
||||
std::string ToString();
|
||||
void Write(std::stringstream& ss);
|
||||
void SetRaw(std::string val);
|
||||
void AddRaw(std::string val);
|
||||
|
||||
boost::property_tree::ptree* pt;
|
||||
bool _base;
|
||||
std::string hackfix;
|
||||
private:
|
||||
// Vector is used to store arrays
|
||||
std::vector<JSON> _vec;
|
||||
// Map is used to store objects
|
||||
std::map<std::string, JSON> _map;
|
||||
// Map insertion order
|
||||
std::vector<std::string> _mapOrder;
|
||||
// Boost variant stores primitive types
|
||||
JSONValue _val;
|
||||
|
||||
JSONValueType _type;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
inline void JSON::Set<JSON>(std::string key, JSON value)
|
||||
inline void JSON::Add(JSON& node)
|
||||
{
|
||||
pt->put_child(key, *value.pt);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void JSON::Add<JSON>(JSON value)
|
||||
{
|
||||
pt->push_back(std::make_pair("", *value.pt));
|
||||
if (_type != JSON_ARRAY) {
|
||||
if (_type != JSON_NULL)
|
||||
throw "Bad type";
|
||||
else
|
||||
_type = JSON_ARRAY;
|
||||
}
|
||||
|
||||
_vec.push_back(node);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
183
src/server/shared/JSON/JSONReader.h
Normal file
183
src/server/shared/JSON/JSONReader.h
Normal file
@ -0,0 +1,183 @@
|
||||
#ifndef JSON_READER_H_
|
||||
#define JSON_READER_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "JSON.h"
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
namespace JSONReader
|
||||
{
|
||||
class SemanticFunctions
|
||||
{
|
||||
public:
|
||||
SemanticFunctions(JSON& node)
|
||||
{
|
||||
_stack.push_back(&node);
|
||||
}
|
||||
|
||||
void BeginObject(char ch)
|
||||
{
|
||||
if (_stack.back()->GetType() == JSON_NULL)
|
||||
_stack.back()->SetType(JSON_OBJECT);
|
||||
else {
|
||||
JSON* node = new JSON(JSON_OBJECT);
|
||||
_stack.push_back(node);
|
||||
}
|
||||
}
|
||||
void EndObject(char ch)
|
||||
{
|
||||
JSON* node = _stack.back();
|
||||
_stack.pop_back();
|
||||
if (_stack.size()) {
|
||||
SetData(*node);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
void BeginArray(char ch)
|
||||
{
|
||||
if (_stack.back()->GetType() == JSON_NULL)
|
||||
_stack.back()->SetType(JSON_ARRAY);
|
||||
else {
|
||||
JSON* node = new JSON(JSON_ARRAY);
|
||||
_stack.push_back(node);
|
||||
}
|
||||
}
|
||||
void EndArray(char ch)
|
||||
{
|
||||
JSON* node = _stack.back();
|
||||
_stack.pop_back();
|
||||
if (_stack.size()) {
|
||||
SetData(*node);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectKey(std::string str)
|
||||
{
|
||||
_nameStack.push_back(str);
|
||||
}
|
||||
|
||||
void String(std::string str)
|
||||
{
|
||||
SetData(str);
|
||||
}
|
||||
|
||||
void BoolTrue(std::string str)
|
||||
{
|
||||
SetData(true);
|
||||
}
|
||||
|
||||
void BoolFalse(std::string str)
|
||||
{
|
||||
SetData(false);
|
||||
}
|
||||
|
||||
void Null(std::string str)
|
||||
{
|
||||
SetData(JSON(JSON_NULL));
|
||||
}
|
||||
|
||||
void Integer(int64 val)
|
||||
{
|
||||
SetData(val);
|
||||
}
|
||||
|
||||
void Double(double val)
|
||||
{
|
||||
SetData(val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SetData(T data)
|
||||
{
|
||||
if (_stack.back()->GetType() == JSON_OBJECT) {
|
||||
_stack.back()->Set<T>(_nameStack.back(), data);
|
||||
_nameStack.pop_back();
|
||||
} else if (_stack.back()->GetType() == JSON_ARRAY)
|
||||
_stack.back()->Add<T>(data);
|
||||
else
|
||||
throw "fail";
|
||||
}
|
||||
private:
|
||||
// Push all nested nodes here
|
||||
std::vector<JSON*> _stack;
|
||||
// Node is added to the main tree when is closed so we need a name stack
|
||||
std::vector<std::string> _nameStack;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct strict_real_policies : qi::real_policies<T>
|
||||
{
|
||||
static bool const expect_dot = true;
|
||||
};
|
||||
|
||||
qi::real_parser<double, strict_real_policies<double> > strict_double;
|
||||
|
||||
template<typename Iterator>
|
||||
struct Grammar : qi::grammar<Iterator, ascii::space_type>
|
||||
{
|
||||
Grammar(SemanticFunctions& smfunc) : _smfunc(smfunc), Grammar::base_type(json)
|
||||
{
|
||||
typedef boost::function<void(char, qi::unused_type, qi::unused_type)> CharFunc;
|
||||
typedef boost::function<void(std::string, qi::unused_type, qi::unused_type)> StrFunc;
|
||||
typedef boost::function<void(double, qi::unused_type, qi::unused_type)> DoubleFunc;
|
||||
typedef boost::function<void(int64, qi::unused_type, qi::unused_type)> IntFunc;
|
||||
|
||||
CharFunc BeginObj(boost::bind(&SemanticFunctions::BeginObject, &_smfunc, _1));
|
||||
CharFunc EndObj(boost::bind(&SemanticFunctions::EndObject, &_smfunc, _1));
|
||||
CharFunc BeginArray(boost::bind(&SemanticFunctions::BeginArray, &_smfunc, _1));
|
||||
CharFunc EndArray(boost::bind(&SemanticFunctions::EndArray, &_smfunc, _1));
|
||||
StrFunc NewKey(boost::bind(&SemanticFunctions::ObjectKey, &_smfunc, _1));
|
||||
StrFunc NewStr(boost::bind(&SemanticFunctions::String, &_smfunc, _1));
|
||||
StrFunc NewTrue(boost::bind(&SemanticFunctions::BoolTrue, &_smfunc, _1));
|
||||
StrFunc NewFalse(boost::bind(&SemanticFunctions::BoolFalse, &_smfunc, _1));
|
||||
StrFunc NewNull(boost::bind(&SemanticFunctions::Null, &_smfunc, _1));
|
||||
DoubleFunc NewDouble(boost::bind(&SemanticFunctions::Double, &_smfunc, _1));
|
||||
IntFunc NewInt(boost::bind(&SemanticFunctions::Integer, &_smfunc, _1));
|
||||
|
||||
json = object | array;
|
||||
object = qi::char_('{')[BeginObj] >> -members >> qi::char_('}')[EndObj];
|
||||
members = pair % ',';
|
||||
pair = string[NewKey] >> ':' >> value;
|
||||
array = qi::char_('[')[BeginArray] >> -elements >> qi::char_(']')[EndArray];
|
||||
elements = value % ',';
|
||||
value = object | array | string[NewStr] | number | qi::string("true")[NewTrue] | qi::string("false")[NewFalse] | qi::string("null")[NewNull];
|
||||
string = qi::lexeme['"' >> *(qi::char_ - '"') >> '"'];
|
||||
number = strict_double[NewDouble] | qi::long_long[NewInt];
|
||||
}
|
||||
|
||||
qi::rule<Iterator, ascii::space_type> json;
|
||||
qi::rule<Iterator, ascii::space_type> object;
|
||||
qi::rule<Iterator, ascii::space_type> members;
|
||||
qi::rule<Iterator, ascii::space_type> pair;
|
||||
qi::rule<Iterator, ascii::space_type> array;
|
||||
qi::rule<Iterator, ascii::space_type> elements;
|
||||
qi::rule<Iterator, ascii::space_type> value;
|
||||
qi::rule<Iterator, std::string(), ascii::space_type> string;
|
||||
qi::rule<Iterator, ascii::space_type> number;
|
||||
|
||||
// Functions
|
||||
SemanticFunctions& _smfunc;
|
||||
};
|
||||
|
||||
inline void Parse(std::string str, JSON& node)
|
||||
{
|
||||
SemanticFunctions smfunc(node);
|
||||
Grammar<std::string::const_iterator> g(smfunc);
|
||||
|
||||
std::string::const_iterator begin = str.begin();
|
||||
std::string::const_iterator end = str.end();
|
||||
|
||||
qi::phrase_parse(begin, end, g, ascii::space);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -43,12 +43,12 @@ bool JSONRPC::Connect(JSONRPCConnectionInfo connInfo)
|
||||
|
||||
JSON JSONRPC::Query(std::string method, JSON params)
|
||||
{
|
||||
JSON request(true);
|
||||
request.Set("jsonrpc", "1.0");
|
||||
request.Set("id", 1);
|
||||
request.Set("method", method);
|
||||
JSON request;
|
||||
request["jsonrpc"] = "1.0";
|
||||
request["id"] = int64(1);
|
||||
request["method"] = method;
|
||||
if (params.Size() > 0)
|
||||
request.Set("params", params);
|
||||
request["params"] = params;
|
||||
std::string jsonstring = request.ToString();
|
||||
|
||||
sLog.Debug(LOG_JSONRPC, "JSONRPC::Query(): JSONString: %s", jsonstring.c_str());
|
||||
@ -61,7 +61,7 @@ JSON JSONRPC::Query(std::string method, JSON params)
|
||||
if (error)
|
||||
{
|
||||
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Error connecting to '%s': %s", _connInfo.Host.c_str(), boost::system::system_error(error).what());
|
||||
return NULL;
|
||||
throw "fail";
|
||||
}
|
||||
|
||||
boost::asio::streambuf request_buf;
|
||||
@ -91,13 +91,13 @@ JSON JSONRPC::Query(std::string method, JSON params)
|
||||
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
|
||||
{
|
||||
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Malformed HTTP Response");
|
||||
return NULL;
|
||||
throw "fail";
|
||||
}
|
||||
|
||||
if (status_code != 200)
|
||||
{
|
||||
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Returned status code: %u", status_code);
|
||||
return NULL;
|
||||
throw "fail";
|
||||
}
|
||||
|
||||
std::vector<std::string> headers;
|
||||
|
Loading…
x
Reference in New Issue
Block a user