init
This commit is contained in:
commit
8d45088064
20 changed files with 974 additions and 0 deletions
161
src/jsonrpctcpclient.cpp
Normal file
161
src/jsonrpctcpclient.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
#include "jsonrpctcpclient.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <json/json.h>
|
||||
#include <iostream>
|
||||
#include <asio/streambuf.hpp>
|
||||
#include <asio/write.hpp>
|
||||
#include <asio/read_until.hpp>
|
||||
#include <asio/read.hpp>
|
||||
#include <asio/buffer.hpp>
|
||||
#include <thread>
|
||||
|
||||
|
||||
JsonRpcTcpClient::JsonRpcTcpClient(const std::string & hostIpAddress, unsigned short tcpPort)
|
||||
: _ioc()
|
||||
, _socket(_ioc)
|
||||
, _jsonRpcId(1)
|
||||
, _tcpStreambuf()
|
||||
, _tcpOutStream(&_tcpStreambuf)
|
||||
, _jsonStreamWriter(nullptr)
|
||||
, _receiveMethodResponseSem(0)
|
||||
, _isStartReceive(false)
|
||||
{
|
||||
Json::StreamWriterBuilder jsonStreamWriterBuilder;
|
||||
jsonStreamWriterBuilder["indentation"] = "";
|
||||
_jsonStreamWriter.reset(jsonStreamWriterBuilder.newStreamWriter());
|
||||
|
||||
_socket.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string(hostIpAddress), tcpPort));
|
||||
}
|
||||
|
||||
JsonRpcTcpClient::~JsonRpcTcpClient()
|
||||
{
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
void JsonRpcTcpClient::bindNotification(const std::string & methodName, const std::function<void(Json::Value)> & notificationHandle)
|
||||
{
|
||||
assert(!_isStartReceive);
|
||||
_notificationHandles.insert(std::make_pair(methodName, notificationHandle));
|
||||
}
|
||||
|
||||
void JsonRpcTcpClient::startReceive()
|
||||
{
|
||||
_isStartReceive = true;
|
||||
std::thread([](JsonRpcTcpClient * thus){thus->receive();}, this).detach();
|
||||
}
|
||||
|
||||
void JsonRpcTcpClient::callNotification(const char * methodName, const Json::Value & params)
|
||||
{
|
||||
// Prepare message
|
||||
Json::Value message;
|
||||
message["jsonrpc"] = "2.0";
|
||||
message["method"] = methodName;
|
||||
message["params"] = params;
|
||||
|
||||
// Send message
|
||||
_jsonStreamWriter->write(message, &_tcpOutStream);
|
||||
_tcpOutStream << static_cast<char>(0x0A);
|
||||
asio::write(_socket, _tcpStreambuf);
|
||||
|
||||
#ifdef JSONRPC_DEBUG
|
||||
// Print message
|
||||
std::cout << "send message ";
|
||||
_jsonStreamWriter->write(message, &std::cout);
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
Json::Value JsonRpcTcpClient::callMethod(const char * methodName, const Json::Value & param)
|
||||
{
|
||||
// Prepare message
|
||||
Json::Value message;
|
||||
message["jsonrpc"] = "2.0";
|
||||
message["method"] = methodName;
|
||||
message["params"] = param;
|
||||
message["id"] = _jsonRpcId;
|
||||
|
||||
// Send message
|
||||
_jsonStreamWriter->write(message, &_tcpOutStream);
|
||||
_tcpOutStream << static_cast<char>(0x0A);
|
||||
asio::write(_socket, _tcpStreambuf);
|
||||
|
||||
#ifdef JSONRPC_DEBUG
|
||||
// Print message
|
||||
std::cout << "send message ";
|
||||
_jsonStreamWriter->write(message, &std::cout);
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
|
||||
// Wait response
|
||||
#ifdef JSONRPC_DEBUG
|
||||
std::cout << "wait response..." << std::endl;
|
||||
#endif
|
||||
_receiveMethodResponseSem.acquire();
|
||||
Json::Value responseJson = _receiveMethodResponseJsonValue;
|
||||
assert(_jsonRpcId == responseJson["id"].asInt());
|
||||
_receiveMethodResponseJsonValue = Json::Value();
|
||||
|
||||
#ifdef JSONRPC_DEBUG
|
||||
// Print response
|
||||
std::cout << "Receive response ";
|
||||
_jsonStreamWriter->write(responseJson, &std::cout);
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
|
||||
_jsonRpcId++;
|
||||
return responseJson["result"];
|
||||
}
|
||||
|
||||
void JsonRpcTcpClient::receive()
|
||||
{
|
||||
asio::streambuf tcpStreambuf;
|
||||
std::istream tcpInStream(&tcpStreambuf);
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Wait message
|
||||
asio::read_until(_socket, tcpStreambuf, 0x0A);
|
||||
#ifdef JSONRPC_DEBUG
|
||||
std::cout << "wait message..." << std::endl;
|
||||
#endif
|
||||
|
||||
// Extract one json message
|
||||
std::string messageJsonStr;
|
||||
std::getline(tcpInStream, messageJsonStr, static_cast<char>(0x0A));
|
||||
|
||||
// Parse this json message
|
||||
Json::CharReaderBuilder builder;
|
||||
JSONCPP_STRING errs;
|
||||
Json::Value messageJson;
|
||||
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
if (!reader->parse(messageJsonStr.c_str(), messageJsonStr.c_str()+messageJsonStr.size(),
|
||||
&messageJson, &errs))
|
||||
throw std::runtime_error(errs);
|
||||
|
||||
// If method response
|
||||
if (messageJson.isMember("id"))
|
||||
{
|
||||
assert(_receiveMethodResponseJsonValue.isNull());
|
||||
_receiveMethodResponseJsonValue = messageJson;
|
||||
_receiveMethodResponseSem.release();
|
||||
}
|
||||
// If notification
|
||||
else
|
||||
{
|
||||
#ifdef JSONRPC_DEBUG
|
||||
// Print notification
|
||||
std::cout << "Receive notification ";
|
||||
_jsonStreamWriter->write(messageJson, &std::cout);
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
// Find the notification and execute it
|
||||
auto it = _notificationHandles.find(messageJson["method"].asString());
|
||||
if (it != _notificationHandles.end())
|
||||
{
|
||||
it->second(messageJson["params"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue