mirror of
https://github.com/GOSTSec/poolserver
synced 2025-01-30 08:24:16 +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
|
// Server
|
||||||
descServer.add_options()
|
descServer.add_options()
|
||||||
("MinDiffTime", boost::program_options::value<uint32_t>()->default_value(100), "Minimum server diff time")
|
("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
|
// Stratum
|
||||||
|
@ -35,6 +35,9 @@ int Server::Run()
|
|||||||
|
|
||||||
//InitDatabase();
|
//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");
|
/*std::vector<byte> test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||||
sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(Crypto::SHA256D(test)).c_str());
|
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());
|
sLog.Info(LOG_SERVER, "RevHash: %s", Util::BinToASCII(Crypto::SHA256D(Util::Reverse(test))).c_str());
|
||||||
|
@ -3,52 +3,84 @@
|
|||||||
|
|
||||||
namespace Stratum
|
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)
|
void Client::OnMiningSubscribe(JSON msg)
|
||||||
{
|
{
|
||||||
_subscribed = true;
|
_subscribed = true;
|
||||||
_extranonce = _server->GetExtranonce();
|
_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;
|
JSON notify;
|
||||||
notify.Add("mining.notify");
|
notify.Add("mining.notify");
|
||||||
notify.Add("abc");
|
notify.Add("ae6812eb4cd7735a302a8a9dd95cf71f");
|
||||||
|
|
||||||
JSON something;
|
|
||||||
something.Add(miningdiff);
|
|
||||||
something.Add(notify);
|
|
||||||
|
|
||||||
JSON result;
|
JSON result;
|
||||||
result.Add(something);
|
result.Add(notify);
|
||||||
ByteBuffer noncebuf;
|
ByteBuffer noncebuf;
|
||||||
noncebuf << _extranonce;
|
noncebuf << _extranonce;
|
||||||
JSON omg;
|
result.Add(Util::BinToASCII(noncebuf.Binary()));
|
||||||
omg.Set("", Util::BinToASCII(noncebuf.Binary()));
|
result.Add(int64(4));
|
||||||
result.Add(omg);
|
|
||||||
JSON shit;
|
|
||||||
shit.Set("", 4);
|
|
||||||
result.Add(shit);
|
|
||||||
|
|
||||||
response.Set("result", result);
|
JSON response;
|
||||||
|
response["id"] = msg["id"].GetInt();
|
||||||
|
response["result"] = result;
|
||||||
|
response["error"];
|
||||||
|
|
||||||
SendMessage(response);
|
SendMessage(response);
|
||||||
|
|
||||||
|
SendJob(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Job Client::GetJob()
|
Job Client::GetJob()
|
||||||
{
|
{
|
||||||
Job job;
|
Job job;
|
||||||
job.work = _server->GetWork();
|
job.block = _server->GetWork();
|
||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace Stratum
|
|||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
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));
|
boost::bind(&Client::_OnReceive, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendJob()
|
void SendJob(bool clean);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendMessage(JSON msg)
|
void SendMessage(JSON msg)
|
||||||
{
|
{
|
||||||
std::string data = msg.ToString();
|
std::string data = msg.ToString();
|
||||||
|
data += '\n';
|
||||||
sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str());
|
sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str());
|
||||||
_socket.send(boost::asio::buffer(data.c_str(), data.length()));
|
_socket.send(boost::asio::buffer(data.c_str(), data.length()));
|
||||||
}
|
}
|
||||||
@ -55,17 +54,17 @@ namespace Stratum
|
|||||||
|
|
||||||
void OnMiningAuthorize(JSON msg)
|
void OnMiningAuthorize(JSON msg)
|
||||||
{
|
{
|
||||||
std::string username = msg["result"][0].Get<std::string>();
|
std::string username = msg["result"][0].GetString();
|
||||||
JSON response;
|
JSON response;
|
||||||
response.Set("id", msg["id"].Get<uint32>());
|
response["id"] = msg["id"].GetInt();
|
||||||
response.Set("error", NULL);
|
response["error"];
|
||||||
response.Set("result", true);
|
response["result"] = true;
|
||||||
SendMessage(response);
|
SendMessage(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnMessage(JSON msg)
|
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());
|
sLog.Debug(LOG_SERVER, "Method: %s", method.c_str());
|
||||||
|
|
||||||
if (method.compare("mining.subscribe") == 0)
|
if (method.compare("mining.subscribe") == 0)
|
||||||
@ -100,7 +99,8 @@ namespace Stratum
|
|||||||
// Jobs
|
// Jobs
|
||||||
bool _subscribed;
|
bool _subscribed;
|
||||||
uint32 _extranonce;
|
uint32 _extranonce;
|
||||||
std::vector<Job> _jobs;
|
std::map<uint64, Job> _jobs;
|
||||||
|
uint64 _jobid;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ namespace Stratum
|
|||||||
class Job
|
class Job
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Bitcoin::BlockPtr work;
|
Bitcoin::BlockPtr block;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ namespace Stratum
|
|||||||
public:
|
public:
|
||||||
Server(asio::io_service& io_service) : _io_service(io_service), _acceptor(io_service), _blockCheckTimer(io_service), _blockHeight(0), _extranonce(0)
|
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()
|
~Server()
|
||||||
@ -104,20 +105,20 @@ namespace Stratum
|
|||||||
|
|
||||||
Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block());
|
Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block());
|
||||||
|
|
||||||
block->version = response["version"].Get<uint32>();;
|
block->version = response["version"].GetInt();
|
||||||
block->prevBlockHash = Util::ASCIIToBin(response["previousblockhash"].Get<std::string>());
|
block->prevBlockHash = Util::ASCIIToBin(response["previousblockhash"].GetString());
|
||||||
|
block->time = response["curtime"].GetInt();
|
||||||
// Set bits
|
// Set bits
|
||||||
ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].Get<std::string>()));
|
ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].GetString()));
|
||||||
bitbuf >> block->bits;
|
bitbuf >> block->bits;
|
||||||
|
|
||||||
// Add coinbase tx
|
// 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
|
// Add other transactions
|
||||||
JSON trans = response["transactions"];
|
JSON trans = response["transactions"];
|
||||||
for (uint64 i = 0; i < trans.Size(); ++i) {
|
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;
|
Bitcoin::Transaction tx;
|
||||||
txbuf >> tx;
|
txbuf >> tx;
|
||||||
block->tx.push_back(tx);
|
block->tx.push_back(tx);
|
||||||
@ -135,7 +136,7 @@ namespace Stratum
|
|||||||
sLog.Debug(LOG_STRATUM, "Checking for new blocks...");
|
sLog.Debug(LOG_STRATUM, "Checking for new blocks...");
|
||||||
|
|
||||||
JSON response = _bitcoinrpc->Query("getinfo");
|
JSON response = _bitcoinrpc->Query("getinfo");
|
||||||
uint32 curBlock = response["blocks"].Get<uint32>();
|
uint32 curBlock = response["blocks"].GetInt();
|
||||||
|
|
||||||
if (curBlock > _blockHeight) {
|
if (curBlock > _blockHeight) {
|
||||||
sLog.Debug(LOG_STRATUM, "New block on network! Height: %u", curBlock);
|
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)
|
Bitcoin::Transaction CreateCoinbaseTX(uint32 blockHeight, BinaryData pubkey, int64 value)
|
||||||
{
|
{
|
||||||
|
// Extranonce placeholder
|
||||||
|
BinaryData extranonce_ph(8, 0);
|
||||||
ByteBuffer scriptsig;
|
ByteBuffer scriptsig;
|
||||||
scriptsig << _blockHeight;
|
scriptsig << _blockHeight << extranonce_ph;
|
||||||
|
|
||||||
Bitcoin::OutPoint outpoint;
|
Bitcoin::OutPoint outpoint;
|
||||||
outpoint.hash.resize(32, 0);
|
outpoint.hash.resize(32, 0);
|
||||||
|
@ -28,6 +28,7 @@ namespace Bitcoin
|
|||||||
|
|
||||||
// Other data
|
// Other data
|
||||||
std::vector<BinaryData> merkleTree;
|
std::vector<BinaryData> merkleTree;
|
||||||
|
uint64 merkleBranches;
|
||||||
|
|
||||||
void BuildMerkleTree()
|
void BuildMerkleTree()
|
||||||
{
|
{
|
||||||
@ -40,6 +41,9 @@ namespace Bitcoin
|
|||||||
++levels;
|
++levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used when sending merkle branches
|
||||||
|
merkleBranches = branches;
|
||||||
|
|
||||||
// Add transactions
|
// Add transactions
|
||||||
for (uint64 i = 0; i < branches; ++i)
|
for (uint64 i = 0; i < branches; ++i)
|
||||||
merkleTree.push_back(tx[std::min(i, tx.size()-1)].GetHash());
|
merkleTree.push_back(tx[std::min(i, tx.size()-1)].GetHash());
|
||||||
|
@ -8,6 +8,13 @@ class ByteBuffer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ByteBuffer(): pointer(0) {}
|
ByteBuffer(): pointer(0) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ByteBuffer(T data): pointer(0)
|
||||||
|
{
|
||||||
|
Append<T>(data);
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer(BinaryData data): pointer(0), vec(data) {}
|
ByteBuffer(BinaryData data): pointer(0), vec(data) {}
|
||||||
|
|
||||||
ByteBuffer& operator<<(ByteBuffer& b)
|
ByteBuffer& operator<<(ByteBuffer& b)
|
||||||
|
@ -1,22 +1,109 @@
|
|||||||
#include "JSON.h"
|
#include "JSON.h"
|
||||||
|
#include "JSONReader.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/foreach.hpp>
|
#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::FromString(std::string jsonstring)
|
||||||
{
|
{
|
||||||
JSON json;
|
JSON node;
|
||||||
json.pt = new boost::property_tree::ptree();
|
JSONReader::Parse(jsonstring, node);
|
||||||
std::stringstream ss;
|
return node;
|
||||||
ss.str(jsonstring);
|
|
||||||
boost::property_tree::json_parser::read_json(ss, *json.pt);
|
|
||||||
return json;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JSON::ToString()
|
std::string JSON::ToString()
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
boost::property_tree::json_parser::write_json(ss, *pt);
|
Write(ss);
|
||||||
return ss.str();
|
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 "Common.h"
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/variant.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#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
|
class JSON
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static JSON FromString(std::string jsonstring);
|
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()
|
~JSON()
|
||||||
{
|
{
|
||||||
//if (_base && pt)
|
|
||||||
// delete pt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
// Arrays
|
||||||
T Get()
|
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);
|
if (_type != JSON_ARRAY) {
|
||||||
json.pt = &pt->get_child(key);
|
if (_type != JSON_NULL)
|
||||||
return json;
|
throw "Bad type";
|
||||||
|
else
|
||||||
|
_type = JSON_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON node;
|
||||||
|
node = val;
|
||||||
|
_vec.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON operator[] (uint32 index)
|
void AddNull()
|
||||||
{
|
{
|
||||||
JSON json(false);
|
if (_type != JSON_ARRAY) {
|
||||||
boost::property_tree::ptree::iterator it = pt->begin();
|
if (_type != JSON_NULL)
|
||||||
for (int i = 0; i < index; ++i)
|
throw "Bad type";
|
||||||
++it;
|
else
|
||||||
boost::property_tree::ptree::value_type& kv = *it;
|
_type = JSON_ARRAY;
|
||||||
json.pt = &kv.second;
|
}
|
||||||
return json;
|
|
||||||
|
JSON node;
|
||||||
|
_vec.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
// Objects
|
||||||
inline void Set(std::string key, T value)
|
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>
|
template<typename T>
|
||||||
inline void Add(T value)
|
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();
|
std::string ToString();
|
||||||
|
void Write(std::stringstream& ss);
|
||||||
|
void SetRaw(std::string val);
|
||||||
|
void AddRaw(std::string val);
|
||||||
|
|
||||||
boost::property_tree::ptree* pt;
|
std::string hackfix;
|
||||||
bool _base;
|
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<>
|
template<>
|
||||||
inline void JSON::Set<JSON>(std::string key, JSON value)
|
inline void JSON::Add(JSON& node)
|
||||||
{
|
{
|
||||||
pt->put_child(key, *value.pt);
|
if (_type != JSON_ARRAY) {
|
||||||
}
|
if (_type != JSON_NULL)
|
||||||
|
throw "Bad type";
|
||||||
template<>
|
else
|
||||||
inline void JSON::Add<JSON>(JSON value)
|
_type = JSON_ARRAY;
|
||||||
{
|
}
|
||||||
pt->push_back(std::make_pair("", *value.pt));
|
|
||||||
|
_vec.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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 JSONRPC::Query(std::string method, JSON params)
|
||||||
{
|
{
|
||||||
JSON request(true);
|
JSON request;
|
||||||
request.Set("jsonrpc", "1.0");
|
request["jsonrpc"] = "1.0";
|
||||||
request.Set("id", 1);
|
request["id"] = int64(1);
|
||||||
request.Set("method", method);
|
request["method"] = method;
|
||||||
if (params.Size() > 0)
|
if (params.Size() > 0)
|
||||||
request.Set("params", params);
|
request["params"] = params;
|
||||||
std::string jsonstring = request.ToString();
|
std::string jsonstring = request.ToString();
|
||||||
|
|
||||||
sLog.Debug(LOG_JSONRPC, "JSONRPC::Query(): JSONString: %s", jsonstring.c_str());
|
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)
|
if (error)
|
||||||
{
|
{
|
||||||
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Error connecting to '%s': %s", _connInfo.Host.c_str(), boost::system::system_error(error).what());
|
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;
|
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/")
|
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
|
||||||
{
|
{
|
||||||
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Malformed HTTP Response");
|
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Malformed HTTP Response");
|
||||||
return NULL;
|
throw "fail";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status_code != 200)
|
if (status_code != 200)
|
||||||
{
|
{
|
||||||
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Returned status code: %u", status_code);
|
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Returned status code: %u", status_code);
|
||||||
return NULL;
|
throw "fail";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> headers;
|
std::vector<std::string> headers;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user