restructure call context, so cached/generated values are now thread-safe "per call" and not globally stored in the JsonAdapter class!

JSON-156
Roker 3 years ago
parent f7043856c3
commit 9b3a0bd4ff

@ -1,5 +1,7 @@
#include "context.hh"
#include "logger.hh"
#include "json-adapter.hh"
namespace
{
@ -11,6 +13,19 @@ namespace
}
bool Context::verify_security_token(const std::string& token) const
{
return ja->verify_security_token(token);
}
// Cache a certain function call. See JSON-155.
void Context::cache(const std::string& func_name, const std::function<void(PEP_SESSION)>& fn)
{
ja->cache(func_name, fn);
}
void Context::store(int position, size_t value)
{
DEBUG_OUT( Log(), "Store value %zu for position %d.", value, position);
@ -29,9 +44,3 @@ size_t Context::retrieve(int position)
throw;
}
}
void Context::clear()
{
obj_store.clear();
}

@ -1,30 +1,37 @@
#ifndef JSON_ADAPTER_CONTEXT_HH
#define JSON_ADAPTER_CONTEXT_HH
#include <string>
#include "json_spirit/json_spirit_value.h"
#include <map>
#include <pEp/pEpEngine.h>
class JsonAdapterBase;
class Context
{
public:
virtual ~Context() = default;
Context(JsonAdapterBase* _ja) : ja{_ja} {}
Context(const Context&) = delete;
void operator=(const Context&) = delete;
virtual bool verify_security_token(const std::string& token) const = 0;
// delegate call to the 'ja' member
bool verify_security_token(const std::string& token) const ;
// Cache a certain function call. See JSON-155.
virtual void cache(const std::string& func_name, const std::function<void(PEP_SESSION)>& fn) = 0;
// delegate call to the 'ja' member
void cache(const std::string& func_name, const std::function<void(PEP_SESSION)>& fn);
// store and retrieve other parameters into the context.
// that allows semantic actions based on other function parameters
// KISS: at the moment only "size_t" objects are supported.
virtual void store(int position, size_t value);
virtual size_t retrieve(int position);
virtual void clear();
void store(int position, size_t value);
size_t retrieve(int position);
void clear();
private:
std::map<int, size_t> obj_store;
JsonAdapterBase* ja;
};
#endif // JSON_ADAPTER_CONTEXT_HH

@ -209,8 +209,6 @@ public:
rs.emplace_back("outParams", std::move(out_params));
rs.emplace_back("return", std::move(ret));
context->clear(); // clear all stored values, if any.
return rs;
}

@ -5,15 +5,27 @@
#include <pEp/message.h>
#include <pEp/sync_api.h>
#include "registry.hh"
#include "context.hh"
#include "logger.hh"
#include "server_version.hh"
#include "json_spirit/json_spirit_value.h"
class SessionRegistry;
class JsonAdapter : public Context
// allow mocking the JsonAdapter in unittest_rpc
class JsonAdapterBase
{
public:
~JsonAdapterBase() = default;
virtual bool verify_security_token(const std::string& s) const = 0;
// Cache a certain function call. See JSON-155.
virtual void cache(const std::string& fn_name, const std::function<void(PEP_SESSION)>& func) = 0;
};
class JsonAdapter : public JsonAdapterBase
{
public:

@ -1,3 +1,4 @@
#include "context.hh"
#include "json_rpc.hh"
#include "json_spirit/json_spirit_utils.h"
#include "json_spirit/json_spirit_writer.h"
@ -72,7 +73,7 @@ js::Object make_request(const std::string& functionName, const js::Array& parame
using json_spirit::find_value;
js::Object call(const FunctionMap& fm, const js::Object& request, Context* context)
js::Object call(const FunctionMap& fm, const js::Object& request, JsonAdapterBase* ja)
{
Logger L("jrpc:call");
int request_id = -1;
@ -86,7 +87,7 @@ js::Object call(const FunctionMap& fm, const js::Object& request, Context* conte
const auto sec_token = find_value(request, "security_token");
const std::string sec_token_s = (sec_token.type()==js::str_type ? sec_token.get_str() : std::string() ); // missing or non-string "security_token" --> empty string.
if( context->verify_security_token(sec_token_s)==false )
if( ja->verify_security_token(sec_token_s)==false )
{
return make_error(JSON_RPC::INVALID_REQUEST, "Invalid request: Wrong security token.", request, request_id);
}
@ -130,7 +131,8 @@ js::Object call(const FunctionMap& fm, const js::Object& request, Context* conte
DEBUG_OUT(L, "method_name=\"" + method_name + "\"\n"
"params=" + js::write(params) );
const js::Value result = fn->second->call(p, context);
Context context{ja};
const js::Value result = fn->second->call(p, &context);
DEBUG_OUT(L, "result=" + js::write(result, js::raw_utf8) );
return make_result(result, request_id);

@ -2,7 +2,6 @@
#define JSON_RPC_HH
#include "json_spirit/json_spirit_value.h"
#include "context.hh"
#include "function_map.hh"
namespace js = json_spirit;
@ -17,11 +16,13 @@ enum class JSON_RPC
INTERNAL_ERROR = -32603,
};
class JsonAdapterBase;
// Server side:
// parse the JSON-RPC 2.0 compatible "request", call the C function
// and create an appropiate "response" object (containing a result or an error)
js::Object call(const FunctionMap& fm, const js::Object& request, Context* context);
js::Object call(const FunctionMap& fm, const js::Object& request, JsonAdapterBase* ja);
// create a JSON-RPC 2.0 compatible result response object
//js::Object make_result(const js::Value& result, int id);

@ -1,5 +1,6 @@
#include <gtest/gtest.h>
#include "json_rpc.hh"
#include "json-adapter.hh"
#include "function_map.hh"
#include "c_string.hh"
#include "json_spirit/json_spirit_reader.h"
@ -24,7 +25,7 @@ std::ostream& operator<<(std::ostream& os, const Value& value)
namespace {
class DummyContext : public Context
class DummyAdapter : public JsonAdapterBase
{
public:
virtual bool verify_security_token(const std::string& token) const override { return true; }
@ -36,7 +37,7 @@ public:
};
DummyContext dummyContext;
DummyAdapter dummyAdapter;
// some example & test functions:
@ -162,7 +163,7 @@ TEST_P( RpcTest, Meh )
js::read_or_throw(v.result, expected_result);
auto r = request;
const js::Value actual_result = call( test_functions, request.get_obj(), &dummyContext);
const js::Value actual_result = call( test_functions, request.get_obj(), &dummyAdapter);
js::Object result_obj = actual_result.get_obj();
js::Object::iterator q = std::find_if(result_obj.begin(), result_obj.end(), [](const js::Pair& v){ return js::Config::get_name(v) == "thread_id"; } );
result_obj.erase( q );

Loading…
Cancel
Save