1
0
mirror of https://github.com/GOSTSec/poolserver synced 2025-02-06 12:04:29 +00:00

Added JSON Library (ALPHA), Added JSONRPC Library (ALPHA), Base64 Encode/Decode

This commit is contained in:
Intel 2013-07-30 01:08:56 +03:00
parent 57c65a4ba2
commit 519cfec904
10 changed files with 343 additions and 9 deletions

View File

@ -15,6 +15,8 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/Database
${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Logging
${CMAKE_SOURCE_DIR}/src/server/shared/JSON
${CMAKE_SOURCE_DIR}/src/server/shared/JSONRPC
${CMAKE_SOURCE_DIR}/src/server/poolserver/Server ${CMAKE_SOURCE_DIR}/src/server/poolserver/Server
${CMAKE_SOURCE_DIR}/src/server/poolserver/Database ${CMAKE_SOURCE_DIR}/src/server/poolserver/Database
${Boost_INCLUDE_DIR} ${Boost_INCLUDE_DIR}

View File

@ -1,9 +1,14 @@
#include "Server.h" #include "Server.h"
#include "Config.h" #include "Config.h"
#include "Log.h" #include "Log.h"
#include "Util.h"
#include "JSON.h"
#include "JSONRPC.h"
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <vector>
#include <string>
bool InitConfig(int argc, char *argv[]) bool InitConfig(int argc, char *argv[])
{ {
@ -78,7 +83,7 @@ bool InitConfig(int argc, char *argv[])
if (!ifs.is_open()) { if (!ifs.is_open()) {
sLog.Error(LOG_GENERAL, "Failed opening config file: %s", sConfig.Get<std::string>("config").c_str()); sLog.Error(LOG_GENERAL, "Failed opening config file: %s", sConfig.Get<std::string>("config").c_str());
return false; return true;
} }
store(parse_config_file(ifs, fileOptions), sConfig.vm); store(parse_config_file(ifs, fileOptions), sConfig.vm);

View File

@ -4,6 +4,8 @@ add_subdirectory(Database)
file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h) file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h)
file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h)
file(GLOB_RECURSE sources_Stratum Stratum/*.cpp Stratum/*.h) file(GLOB_RECURSE sources_Stratum Stratum/*.cpp Stratum/*.h)
file(GLOB_RECURSE sources_JSON JSON/*.cpp JSON/*.h)
file(GLOB_RECURSE sources_JSONRPC JSONRPC/*.cpp JSONRPC/*.h)
file(GLOB sources_localdir *.cpp *.h) file(GLOB sources_localdir *.cpp *.h)
@ -12,6 +14,8 @@ set(sources_Shared
${sources_Database} ${sources_Database}
${sources_Logging} ${sources_Logging}
${sources_Stratum} ${sources_Stratum}
${sources_JSON}
${sources_JSONRPC}
${sources_localdir} ${sources_localdir}
) )
@ -20,6 +24,8 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Configuration ${CMAKE_CURRENT_SOURCE_DIR}/Configuration
${CMAKE_CURRENT_SOURCE_DIR}/Database ${CMAKE_CURRENT_SOURCE_DIR}/Database
${CMAKE_CURRENT_SOURCE_DIR}/Logging ${CMAKE_CURRENT_SOURCE_DIR}/Logging
${CMAKE_CURRENT_SOURCE_DIR}/JSON
${CMAKE_CURRENT_SOURCE_DIR}/JSONRPC
${Boost_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
${MYSQL_INCLUDE_DIR} ${MYSQL_INCLUDE_DIR}
) )

View File

@ -0,0 +1,22 @@
#include "JSON.h"
#include <sstream>
#include <algorithm>
#include <vector>
#include <boost/foreach.hpp>
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;
}
std::string JSON::ToString()
{
std::stringstream ss;
boost::property_tree::json_parser::write_json(ss, *pt);
return ss.str();
}

View File

@ -0,0 +1,80 @@
#ifndef JSON_H_
#define JSON_H_
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/cstdint.hpp>
#include <string>
#include <utility>
class JSON
{
public:
static JSON FromString(std::string jsonstring);
JSON(bool base = true) : _base(base), pt(NULL)
{
if (base)
pt = new boost::property_tree::ptree();
}
~JSON()
{
//if (_base && pt)
// delete pt;
}
template<class T>
T Get(std::string key)
{
return pt->get<T>(key);
}
JSON operator[] (std::string key)
{
JSON json(false);
json.pt = &pt->get_child(key);
return json;
}
JSON operator[] (int index)
{
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;
}
template<class T>
inline void Set(std::string key, T value)
{
pt->put<T>(key, value);
}
template<class T>
inline void Add(T value)
{
pt->push_back(std::make_pair("", value));
}
uint64_t Size()
{
return pt->size();
}
std::string ToString();
boost::property_tree::ptree* pt;
bool _base;
};
template<>
inline void JSON::Set<JSON>(std::string key, JSON value)
{
pt->put_child(key, *value.pt);
}
#endif

View File

@ -0,0 +1,127 @@
#include "JSONRPC.h"
#include <boost/asio.hpp>
#include <boost/exception/all.hpp>
#include "Util.h"
#include "Log.h"
bool JSONRPC::Connect(JSONRPCConnectionInfo connInfo)
{
_connInfo = connInfo;
if (_connInfo.B64Auth.empty())
_connInfo.B64Auth = Util::ToBase64(_connInfo.User + ":" + _connInfo.Pass, false);
sLog.Debug(LOG_JSONRPC, "JSONRPC::Connect(): B64Auth: %s", _connInfo.B64Auth.c_str());
boost::asio::ip::tcp::resolver resolver(_ios);
boost::asio::ip::tcp::resolver::query q(_connInfo.Host, _connInfo.Port);
boost::asio::ip::tcp::resolver::iterator epi = resolver.resolve(q);
boost::asio::ip::tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
while (error && epi != end)
{
_sock.close();
_sock.connect(*epi, error);
}
if (error)
{
sLog.Error(LOG_JSONRPC, "JSONRPC::Connect(): Error connecting to '%s': %s", _connInfo.Host.c_str(), boost::system::system_error(error).what());
return false;
}
_ep = *epi;
_sock.close();
return true;
}
JSON JSONRPC::Query(std::string method, JSON params)
{
JSON request(true);
request.Set("jsonrpc", "1.0");
request.Set("id", 1);
request.Set("method", method);
if (params.Size() > 0)
request.Set("params", params);
std::string jsonstring = request.ToString();
sLog.Debug(LOG_JSONRPC, "JSONRPC::Query(): JSONString: %s", jsonstring.c_str());
boost::system::error_code error;
_sock.close();
_sock.connect(_ep, error);
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;
}
boost::asio::streambuf request_buf;
std::ostream request_info(&request_buf);
request_info << "POST / HTTP/1.1\n";
request_info << "Host: 127.0.0.1\n";
request_info << "Content-Type: application/json-rpc\n";
request_info << "Authorization: Basic " << _connInfo.B64Auth << "\n";
request_info << "Content-Length: " << jsonstring.size() << "\n\n";
request_info << jsonstring;
boost::asio::write(_sock, request_buf);
boost::asio::streambuf response;
boost::asio::read_until(_sock, response, "\n");
std::istream response_stream(&response);
std::string http_version;
uint32_t status_code;
std::string status_message;
response_stream >> http_version >> status_code;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Malformed HTTP Response");
return NULL;
}
if (status_code != 200)
{
sLog.Error(LOG_JSONRPC, "JSONRPC::Query(): Returned status code: %u", status_code);
return NULL;
}
std::vector<std::string> headers;
std::string header;
while (std::getline(response_stream, header) && header != "\r")
headers.push_back(header);
std::string jsonresponse = "";
if (response.size() > 0) {
std::ostringstream oss;
oss << &response;
jsonresponse += oss.str();
}
// Read until EOF, writing data to output as we go.
while(boost::asio::read(_sock, response, boost::asio::transfer_at_least(1), error)){
std::ostringstream oss;
oss << &response;
jsonresponse += oss.str();
}
_sock.close();
sLog.Debug(LOG_JSONRPC, "JSONRPC::Query(): JSON Response: %s", jsonresponse.c_str());
return JSON::FromString(jsonresponse);
}

View File

@ -0,0 +1,34 @@
#ifndef JSONRPC_H_
#define JSONRPC_H_
// Some of the JSON RPC code was written by https://github.com/bytemaster/cpp_bitcoin_rpc
#include <boost/cstdint.hpp>
#include <boost/asio.hpp>
#include <string>
#include "JSON.h"
struct JSONRPCConnectionInfo
{
std::string Host;
std::string Port;
std::string User;
std::string Pass;
std::string B64Auth;
};
class JSONRPC
{
public:
JSONRPC(): _sock(_ios) {}
bool Connect(JSONRPCConnectionInfo conninfo);
JSON Query(std::string method, JSON params = JSON::FromString("[]"));
private:
JSONRPCConnectionInfo _connInfo;
boost::asio::io_service _ios;
boost::asio::ip::tcp::socket _sock;
boost::asio::ip::tcp::endpoint _ep;
};
#endif

View File

@ -16,7 +16,9 @@ enum LogType
{ {
LOG_GENERAL = 0, LOG_GENERAL = 0,
LOG_SERVER = 1, LOG_SERVER = 1,
LOG_DATABASE = 2 LOG_DATABASE = 2,
LOG_JSON = 3,
LOG_JSONRPC = 4
}; };
enum LogLevel enum LogLevel

View File

@ -1,5 +1,7 @@
#include "Util.h" #include "Util.h"
#include <boost/algorithm/string.hpp>
std::string Util::Date(const char* format, bool utc) std::string Util::Date(const char* format, bool utc)
{ {
boost::posix_time::ptime now; boost::posix_time::ptime now;
@ -15,3 +17,28 @@ std::string Util::Date(const char* format, bool utc)
return ss.str(); return ss.str();
} }
std::string Util::ToBase64(std::string input, bool linebreaks)
{
uint32_t writePaddChars = (3 - input.length() % 3) % 3;
if (linebreaks) {
std::string base64(it_base64_lb_t(input.begin()), it_base64_lb_t(input.end()));
base64.append(writePaddChars, '=');
return base64;
} else {
std::string base64(it_base64_t(input.begin()), it_base64_t(input.end()));
base64.append(writePaddChars, '=');
return base64;
}
}
std::string Util::FromBase64(std::string input)
{
boost::algorithm::trim(input);
uint32_t paddChars = count(input.begin(), input.end(), '=');
std::replace(input.begin(), input.end(), '=', 'A'); // replace '=' by base64 encoding of '\0'
std::string result(it_binary_t(input.begin()), it_binary_t(input.end())); // decode
result.erase(result.end() - paddChars, result.end()); // erase padding '\0' characters
return result;
}

View File

@ -4,9 +4,15 @@
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <queue> #include <queue>
#include <string>
#include <boost/date_time.hpp> #include <boost/date_time.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
namespace Util namespace Util
{ {
@ -73,6 +79,29 @@ namespace Util
virtual void Work() = 0; virtual void Work() = 0;
boost::thread* _thread; boost::thread* _thread;
}; };
// Base64 encode/decode functions by http://stackoverflow.com/users/1132850/piquer
typedef boost::archive::iterators::insert_linebreaks
<
boost::archive::iterators::base64_from_binary
<
boost::archive::iterators::transform_width<std::string::const_iterator, 6, 8>
>, 72
> it_base64_lb_t;
typedef boost::archive::iterators::base64_from_binary
<
boost::archive::iterators::transform_width<std::string::const_iterator, 6, 8>
> it_base64_t;
typedef boost::archive::iterators::transform_width
<
boost::archive::iterators::binary_from_base64<std::string::const_iterator>, 8, 6
> it_binary_t;
std::string ToBase64(std::string input, bool linebreaks = true);
std::string FromBase64(std::string input);
} }
#endif #endif