merge "JSON-123" into "sync" branch

JSON-127
Lars Rohwedder 4 years ago
commit 2df30609f4

@ -17,7 +17,7 @@
pre.red {white-space:pre; background-color:#d99; }
</style>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="pep_functions.js"></script>
<script type="text/javascript" src="pEp_functions.js"></script>
<script type="text/javascript" src="interactive.js"></script>
</head>
<body>
@ -67,7 +67,7 @@
<div id="doc_out" style="background-color:white;border:1px black solid; padding:10px;"></div>
<script type="text/javascript">
init_pep_functions();
init_pEp_functions();
on_select_change();
</script>

@ -542,9 +542,9 @@ function prepare_call(f)
function on_select_change()
{
var fn = $( "#fn_name" ).val();
for(var i=0, len=pep_functions.length; i<len; ++i)
for(var i=0, len=pEp_functions.length; i<len; ++i)
{
var f = pep_functions[i];
var f = pEp_functions[i];
if(f.name == fn)
{
prepare_call(f);
@ -553,12 +553,12 @@ function on_select_change()
}
function init_pep_functions()
function init_pEp_functions()
{
var optionList = "";
for(var i=0, len=pep_functions.length; i<len; ++i)
for(var i=0, len=pEp_functions.length; i<len; ++i)
{
var f = pep_functions[i];
var f = pEp_functions[i];
optionList += '<option' + (f.separator? ' disabled> —— ':'>') + f.name + "</option>\n";
}
document.getElementById("fn_name").innerHTML = optionList;
@ -623,9 +623,9 @@ function create_doc()
var fd = format_def[format_name];
var output = "";
for(var i=0, len=pep_functions.length; i<len; ++i)
for(var i=0, len=pEp_functions.length; i<len; ++i)
{
var f = pep_functions[i];
var f = pEp_functions[i];
if(f.separator)
{
if(output.length > 0)

@ -29,7 +29,8 @@ ifdef BUILD_CONFIG
$(info ================================================)
endif
NO_SOURCE=main.cc servertest.cc unittest_json.cc unittest_nfc.cc
# These source files shall _not_ be part of the libjson-adapter.a:
NO_SOURCE=$(wildcard mini-adapter-*.cc) servertest.cc $(wildcard unittest_*.cc)
ALL_SOURCE=$(filter-out $(NO_SOURCE),$(wildcard json_spirit/*.cpp))
ALL_SOURCE+= prefix-config.cc
@ -84,26 +85,23 @@ endif
.PHONY: all
all: $(TARGET) $(TARGET_TEST) $(TARGET_GTEST)
$(TARGET): main.o libjson-adapter.a
$(TARGET): mini-adapter-main.o mini-adapter-impl.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@
$(TARGET)-static: main.o libjson-adapter.a
$(TARGET)-static: mini-adapter-main.o mini-adapter-impl.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -static -o $@
$(TARGET_TEST): servertest.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@
$(TARGET_GTEST): unittest_json.o unittest_nfc.o unittest_decompose.o unittest_rpc.o \
unittest_logger.o unittest_pep.o \
unittest_logger.o unittest_pEp.o \
gtest-all.o gtest_main.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@
libjson-adapter.a: $(ALL_OBJECTS)
$(AR) rcs $@ $^
prefix-config.cc:
echo '// This file is generated by make. Edit the Makefile, not this file!\n#include "prefix-config.hh" \nconst char* const html_directory = "html";\n' > $@
gtest-all.o: $(GTEST_DIR)/src/gtest-all.cc
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -o $@ -c $<
@ -144,7 +142,6 @@ clean:
rm -vf *.o json_spirit/*.o
rm -vf *.a json_spirit/*.a
rm -vf *.d json_spirit/*.d
rm -vf prefix-config.cc
.PHONY: run
run:

@ -37,7 +37,7 @@ PREFIX=/usr
HTML_DIRECTORY=$(PREFIX)/share/pEp/json-adapter/html
# Filename of the pEp JSON Server Adapter binary
TARGET=pep-json-server
TARGET=pEp-mini-json-adapter
# Filename of the pEp JSON Server Adapter testing binary
TARGET_TEST=servertest
@ -67,7 +67,9 @@ else ifeq ($(BUILD_FOR),Darwin)
CXX=c++ -std=c++11 -fPIC
endif
CPPFLAGS=-isystem $(GTEST_DIR)/include
HTML_DIR ?= "html"
CPPFLAGS=-isystem $(GTEST_DIR)/include -DHTML_DIR=$(HTML_DIR)
ifeq ($(BUILD_FOR),Linux)
CXXFLAGS=-fstack-protector-all -fdiagnostics-color=always

@ -5,9 +5,9 @@
#include "prefix-config.hh"
#include "json-adapter.hh"
#include "function_map.hh"
#include "pep-types.hh"
#include "pEp-types.hh"
#include "json_rpc.hh"
#include "pep-utils.hh"
#include "pEp-utils.hh"
#include "logger.hh"
#include "server_version.hh"
@ -75,11 +75,6 @@ using In_Pep_Session = In<PEP_SESSION, ParamFlag::NoInput>;
// these are the pEp functions that are callable by the client
const FunctionMap functions = {
FP( "startKeySync", new Func<void, In<JsonAdapter*,ParamFlag::NoInput>>( &JsonAdapter::startSync) ),
FP( "stopKeySync", new Func<void, In<JsonAdapter*,ParamFlag::NoInput>>( &JsonAdapter::stopSync ) ),
FP( "startKeyserverLookup", new Func<void>( &JsonAdapter::startKeyserverLookup) ),
FP( "stopKeyserverLookup", new Func<void>( &JsonAdapter::stopKeyserverLookup ) ),
// from message_api.h
FP( "Message API", new Separator ),
FP( "encrypt_message", new Func<PEP_STATUS, In_Pep_Session, In<message*>, In<stringlist_t*>, Out<message*>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &encrypt_message ) ),
@ -113,7 +108,7 @@ const FunctionMap functions = {
FP( "unset_identity_flags" , new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<identity_flags_t>>( &unset_identity_flags) ),
FP( "MIME message handling", new Separator),
FP( "mime_decode_message", new Func<PEP_STATUS, In<c_string>, In<std::size_t>, Out<message*>>( &mime_decode_message) ),
FP( "mime_decode_message", new Func<PEP_STATUS, In<c_string>, In<std::size_t>, Out<message*>, Out<bool>>( &mime_decode_message) ),
FP( "Low level Key Management API", new Separator),
FP( "generate_keypair", new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &generate_keypair) ),
@ -278,7 +273,7 @@ void ev_server::OnGetFunctions(evhttp_request* req, void*)
"var server_version_name = \"" + version.name + "\";\n"
"var server_version = \"" + version.major_minor_patch() + "\";\n"
"var add_sharks = " + (add_sharks?"true":"false") + ";\n"
"var pep_functions = ";
"var pEp_functions = ";
js::Array jsonfunctions;
for(const auto& f : functions)

@ -13,19 +13,18 @@
#include <functional>
#include <tuple>
#include <mutex>
#include "json-adapter.hh"
#include "daemonize.hh"
#include "pep-types.hh"
#include "pEp-types.hh"
#include "json_rpc.hh"
#include "security-token.hh"
#include "pep-utils.hh"
#include "pEp-utils.hh"
#include "ev_server.hh"
#include "logger.hh"
#include "server_version.hh"
#include <pEp/keymanagement.h>
#include <pEp/call_with_lock.hh>
#include <pEp/status_to_string.hh> // from libpEpAdapter.
#include <pEp/locked_queue.hh>
@ -74,35 +73,14 @@ auto ThreadDeleter = [](std::thread* t)
typedef std::unique_ptr<std::thread, decltype(ThreadDeleter)> ThreadPtr;
typedef std::vector<ThreadPtr> ThreadPool;
// keyserver lookup
utility::locked_queue< pEp_identity*, &free_identity> keyserver_lookup_queue;
PEP_SESSION keyserver_lookup_session = nullptr; // FIXME: what if another adapter started it already?
ThreadPtr keyserver_lookup_thread{nullptr, ThreadDeleter};
std::mutex js_mutex;
// TODO: use && and std::forward<> to avoid copying of the arguments.
// It is not relevant, yet, because at the moment we use this function template only
// for init() and release() which have cheap-to-copy pointer parameters only
template<class R, class... Args>
R call_with_lock( R(*fn)(Args...), Args... args)
{
std::lock_guard<std::mutex> L(js_mutex);
return fn(args...);
}
// *sigh* necessary because messageToSend() has no obj pointer anymore. :-(
JsonAdapter* ja_singleton = 0;
JsonAdapter* ja_singleton = nullptr;
inject_sync_event_t sync_fn = nullptr; // *sigh* ugly, but the Engine's API requires it.
} // end of anonymous namespace
PEP_SESSION JsonAdapter::first_session = nullptr;
typedef std::pair<std::string, unsigned> EventListenerKey;
struct EventListenerValue
@ -127,7 +105,6 @@ struct JsonAdapter::Internal
unsigned port = 0;
unsigned request_count = 0;
evutil_socket_t sock = -1;
bool shall_sync = false; // just hold the value from config/command line.
bool running = false;
bool silent = false;
bool ignore_session_error = false;
@ -135,12 +112,6 @@ struct JsonAdapter::Internal
ThreadPool threads;
PEP_SESSION session = nullptr;
// Sync
utility::locked_queue< Sync_event*, &free_Sync_event> sync_queue;
PEP_SESSION sync_session = nullptr;
ThreadPtr sync_thread{nullptr, ThreadDeleter};
explicit Internal()
: Log("JAI")
{}
@ -150,14 +121,11 @@ struct JsonAdapter::Internal
~Internal()
{
stopSync();
if(session)
call_with_lock(&release, session);
pEp::call_with_lock(&release, session);
session=nullptr;
}
void stopSync();
static
void requestDone(evhttp_request* req, void* userdata)
{
@ -211,58 +179,7 @@ struct JsonAdapter::Internal
addToArray( param_array, params...);
return makeAndDeliverRequest(msg_name, param_array);
}
int injectSyncMsg(Sync_event* msg)
{
sync_queue.push_back(msg);
return 0;
}
int injectIdentity(pEp_identity* idy)
{
keyserver_lookup_queue.push_back(idy);
return 0;
}
Sync_event* retrieveNextSyncMsg(unsigned timeout)
{
Sync_event* msg = nullptr;
if(timeout)
{
const bool success = sync_queue.try_pop_front(msg, std::chrono::seconds(timeout));
if(!success)
{
// this is timeout occurrence
return new_sync_timeout_event();
}
}else{
msg = sync_queue.pop_front();
}
return msg;
}
pEp_identity* retrieveNextIdentity()
{
return keyserver_lookup_queue.pop_front();
}
void* syncThreadRoutine(void* arg)
{
PEP_STATUS status = call_with_lock(&init, &sync_session, &JsonAdapter::messageToSend, &JsonAdapter::injectSyncMsg);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot init sync_session! status: " + ::pEp::status_to_string(status));
status = register_sync_callbacks(sync_session,
(void*) this,
JsonAdapter::notifyHandshake,
JsonAdapter::retrieveNextSyncMsg);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot register sync callbacks! status: " + ::pEp::status_to_string(status));
status = do_sync_protocol(sync_session, arg); // does the whole work
sync_queue.clear(); // remove remaining messages
return (void*) status;
}
};
@ -356,141 +273,11 @@ PEP_STATUS JsonAdapter::notifyHandshake(pEp_identity* self, pEp_identity* partne
}
// BEWARE: msg is 1st parameter, obj is second!!!
int JsonAdapter::injectSyncMsg(Sync_event* msg, void* obj)
{
// JsonAdapter* ja = static_cast<JsonAdapter*>(obj);
return ja_singleton->i->injectSyncMsg(msg);
}
Sync_event* JsonAdapter::retrieveNextSyncMsg(void* obj, unsigned timeout)
{
// JsonAdapter* ja = static_cast<JsonAdapter*>(obj);
ja_singleton->check_guard();
return ja_singleton->i->retrieveNextSyncMsg(timeout);
}
void* JsonAdapter::syncThreadRoutine(void* arg)
{
// JsonAdapter* ja = static_cast<JsonAdapter*>(arg);
return ja_singleton->i->syncThreadRoutine(arg);
}
void JsonAdapter::startSync()
{
check_guard();
i->sync_queue.clear();
// status = attach_sync_session(i->session, i->sync_session);
// if(status != PEP_STATUS_OK)
// throw std::runtime_error("Cannot attach to sync session! status: " + status_to_string(status));
i->sync_thread.reset( new std::thread( JsonAdapter::syncThreadRoutine, (void*)this ) );
}
void JsonAdapter::stopSync()
{
check_guard();
i->stopSync();
}
void JsonAdapter::Internal::stopSync()
{
// No sync session active
if(sync_session == nullptr)
return;
sync_queue.push_front(NULL);
sync_thread->join();
unregister_sync_callbacks(sync_session);
sync_queue.clear();
call_with_lock(&release, sync_session);
sync_session = nullptr;
}
void JsonAdapter::startKeyserverLookup()
{
if(keyserver_lookup_session)
throw std::runtime_error("KeyserverLookup already started.");
PEP_STATUS status = call_with_lock(&init, &keyserver_lookup_session, &JsonAdapter::messageToSend, &JsonAdapter::injectSyncMsg);
if(status != PEP_STATUS_OK || keyserver_lookup_session==nullptr)
{
throw std::runtime_error("Cannot create keyserver lookup session! status: " + ::pEp::status_to_string(status));
}
keyserver_lookup_queue.clear();
status = register_examine_function(keyserver_lookup_session,
JsonAdapter::examineIdentity,
&keyserver_lookup_session // nullptr is not accepted, so any dummy ptr is used here
);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot register keyserver lookup callbacks! status: " + ::pEp::status_to_string(status));
keyserver_lookup_thread.reset( new std::thread( JsonAdapter::keyserverLookupThreadRoutine, &keyserver_lookup_session /* just a dummy */ ) );
}
void JsonAdapter::stopKeyserverLookup()
{
// No keyserver lookup session active
if(keyserver_lookup_session == nullptr)
return;
keyserver_lookup_queue.push_front(NULL);
keyserver_lookup_thread->join();
// there is no unregister_examine_callback() function. hum...
keyserver_lookup_queue.clear();
call_with_lock(&release, keyserver_lookup_session);
keyserver_lookup_session = nullptr;
}
int JsonAdapter::examineIdentity(pEp_identity* idy, void* obj)
{
// JsonAdapter* ja = static_cast<JsonAdapter*>(obj);
return ja_singleton->i->injectIdentity(idy);
}
pEp_identity* JsonAdapter::retrieveNextIdentity(void* obj)
{
// JsonAdapter* ja = static_cast<JsonAdapter*>(obj);
return ja_singleton->i->retrieveNextIdentity();
}
void* JsonAdapter::keyserverLookupThreadRoutine(void* arg)
{
PEP_STATUS status = do_keymanagement(
&JsonAdapter::retrieveNextIdentity,
arg); // does the whole work
keyserver_lookup_queue.clear();
return (void*) status;
}
JsonAdapter::JsonAdapter()
: guard_0(Guard_0)
, i(new Internal{})
, guard_1(Guard_1)
{
if(!ja_singleton)
{
ja_singleton = this;
}
i->eventBase.reset(event_base_new());
if (!i->eventBase)
throw std::runtime_error("Failed to create new base_event.");
@ -505,7 +292,6 @@ JsonAdapter::~JsonAdapter()
{
check_guard();
Log() << "~JsonAdapter(): " << session_registry.size() << " sessions registered.";
stopSync();
this->shutdown(nullptr);
Log() << "\t After stopSync() and shutdown() there are " << session_registry.size() << " sessions registered.";
delete i;
@ -513,14 +299,6 @@ JsonAdapter::~JsonAdapter()
}
JsonAdapter& JsonAdapter::do_sync(bool _do_sync)
{
check_guard();
i->shall_sync = _do_sync;
return *this;
}
JsonAdapter& JsonAdapter::ignore_session_errors(bool _ig)
{
check_guard();
@ -544,22 +322,6 @@ void JsonAdapter::prepare_run(const std::string& address, unsigned start_port, u
i->start_port = start_port;
i->end_port = end_port;
if(first_session == nullptr) // okay, we are the 1st:
{
// create a dummy session just to see whether the Engine is functional.
// reason: here we still can log errors to stderr, because prepare_run() is called before daemonize().
PEP_STATUS status = call_with_lock(&init, &first_session, &JsonAdapter::messageToSend, &JsonAdapter::injectSyncMsg);
if(status != PEP_STATUS_OK || first_session==nullptr)
{
const std::string error_msg = "Cannot create first session! PEP_STATUS: " + ::pEp::status_to_string(status) + ".";
std::cerr << error_msg << std::endl; // Log to stderr intentionally, so Enigmail can grab that error message easily.
if( ! i->ignore_session_error)
{
throw std::runtime_error(error_msg);
}
}
}
Log() << "ThreadFunc: thread id " << std::this_thread::get_id() << ". \n Registry: " << to_string( session_registry );
unsigned port_ofs = 0;
@ -598,7 +360,7 @@ void JsonAdapter::threadFunc()
if(q==session_registry.end())
{
i->session = nullptr;
PEP_STATUS status = call_with_lock(&init, &i->session, &JsonAdapter::messageToSend, &JsonAdapter::injectSyncMsg); // release(session) in ThreadDeleter
PEP_STATUS status = pEp::call_with_lock(&init, &i->session, &JsonAdapter::messageToSend, sync_fn); // release(session) in ThreadDeleter
if(status != PEP_STATUS_OK || i->session==nullptr)
{
const std::string error_msg = "Cannot create session! PEP_STATUS: " + ::pEp::status_to_string(status) + ".";
@ -611,11 +373,6 @@ void JsonAdapter::threadFunc()
session_registry.emplace(id, this);
L << Logger::Info << "\tcreated new session for this thread: " << static_cast<void*>(i->session) << ".";
if(i->shall_sync && i->session) // startSync() does not make sense without session.
{
L << Logger::Info << "\tstartSync()...";
startSync();
}
}else{
L << Logger::Info << "\tsession for this thread: " << static_cast<void*>(q->second) << ".";
}
@ -632,7 +389,7 @@ void JsonAdapter::threadFunc()
if(i->deliver_html)
{
evhttp_set_cb(evHttp.get(), "/pep_functions.js" , ev_server::OnGetFunctions , this);
evhttp_set_cb(evHttp.get(), "/pEp_functions.js" , ev_server::OnGetFunctions , this);
evhttp_set_gencb(evHttp.get(), ev_server::OnOtherRequest, nullptr);
}
@ -814,10 +571,27 @@ void JsonAdapter::check_guard() const
}
void JsonAdapter::global_shutdown()
std::recursive_mutex get_instance_mutex;
JsonAdapter& JsonAdapter::getInstance()
{
std::lock_guard<std::recursive_mutex> L(get_instance_mutex);
if(!ja_singleton)
{
ja_singleton = new JsonAdapter();
}
return *ja_singleton;
}
JsonAdapter& JsonAdapter::startup(inject_sync_event_t se)
{
call_with_lock(&release, JsonAdapter::first_session);
JsonAdapter::first_session = nullptr;
sync_fn = se;
JsonAdapter& ja = getInstance();
ja.prepare_run("127.0.0.1", 4223, 9999);
ja.run();
return ja;
}

@ -12,8 +12,6 @@
class JsonAdapter : public Context
{
public:
// creates an instance of the JSON adapter. It tries to bind the first available port in the given range
JsonAdapter();
// calls shutdown() on the instance if it is still running().
virtual ~JsonAdapter();
@ -29,7 +27,6 @@ public:
// these functions shall be called before prepare_run()!
// only if do_sync== true the keysync thread is stared and the keysync callbacks are registered.
JsonAdapter& do_sync(bool _do_sync);
JsonAdapter& ignore_session_errors(bool _ig);
// if called with "false" the JSON Adpapter would no longer deliver HTML and JavaScript files, only handle JSON-RPC requests
@ -70,29 +67,15 @@ public:
static PEP_STATUS messageToSend(message* msg);
static PEP_STATUS notifyHandshake(pEp_identity* self, pEp_identity* partner, sync_handshake_signal signal);
// BEWARE: msg is 1st parameter, obj is second!!!
static int injectSyncMsg(Sync_event* msg, void* obj);
static Sync_event* retrieveNextSyncMsg(void* obj, unsigned timeout);
static void* syncThreadRoutine(void* arg);
void startSync();
void stopSync();
static void startKeyserverLookup();
static void stopKeyserverLookup();
static int examineIdentity(pEp_identity*, void* obj);
static pEp_identity* retrieveNextIdentity(void* obj);
static void* keyserverLookupThreadRoutine(void* arg);
Logger::Stream Log(Logger::Severity s = Logger::Severity::Debug) const;
// will throw logic_error if guard variables contains illegal values, which means: *this is not a valid JsonAdapter object!
void check_guard() const;
// calls release(first_session).
static
void global_shutdown();
static JsonAdapter& getInstance();
// Very ugly: that function ptr has to be known to the JA before any instance is created. -.-
static JsonAdapter& startup(inject_sync_event_t inject_fn);
//private:
struct Internal;
@ -101,14 +84,15 @@ public:
unsigned long long guard_1;
private:
// creates the one and only instance of the JSON adapter.
JsonAdapter();
static
void staticThreadFunc(JsonAdapter* that) { that->threadFunc(); }
void threadFunc();
std::exception_ptr initExcept;
// albait not documented, the first PEP_SESSION is special: It must be alive as long as any other PEP_SESSIONS are living.
static PEP_SESSION first_session;
};
// just for debug:

@ -0,0 +1,166 @@
#include "mini-adapter-impl.hh"
#include "json-adapter.hh"
#include <thread>
#include <pEp/keymanagement.h>
#include <pEp/call_with_lock.hh>
#include <pEp/status_to_string.hh> // from libpEpAdapter.
#include <pEp/locked_queue.hh>
namespace pEp {
namespace mini {
typedef std::unique_ptr<std::thread> ThreadPtr;
// keyserver lookup
utility::locked_queue< pEp_identity*, &free_identity> keyserver_lookup_queue;
PEP_SESSION keyserver_lookup_session = nullptr; // FIXME: what if another adapter started it already?
ThreadPtr keyserver_lookup_thread;
utility::locked_queue< Sync_event*, &free_Sync_event> sync_queue;
PEP_SESSION sync_session = nullptr;
ThreadPtr sync_thread;
int injectSyncMsg(Sync_event* msg, void* /* management */)
{
sync_queue.push_back(msg);
return 0;
}
int injectIdentity(pEp_identity* idy)
{
keyserver_lookup_queue.push_back(idy);
return 0;
}
Sync_event* retrieveNextSyncMsg(void* /*management*/, unsigned timeout)
{
Sync_event* msg = nullptr;
if(timeout)
{
const bool success = sync_queue.try_pop_front(msg, std::chrono::seconds(timeout));
if(!success)
{
// this is timeout occurrence
return new_sync_timeout_event();
}
}else{
msg = sync_queue.pop_front();
}
return msg;
}
pEp_identity* retrieveNextIdentity(void* /*userdata*/)
{
return keyserver_lookup_queue.pop_front();
}
void* syncThreadRoutine(void* arg)
{
PEP_STATUS status = pEp::call_with_lock(&init, &sync_session, &JsonAdapter::messageToSend, &injectSyncMsg);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot init sync_session! status: " + ::pEp::status_to_string(status));
status = register_sync_callbacks(sync_session,
(void*) -1,
&JsonAdapter::notifyHandshake,
&retrieveNextSyncMsg);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot register sync callbacks! status: " + ::pEp::status_to_string(status));
status = do_sync_protocol(sync_session, arg); // does the whole work
sync_queue.clear(); // remove remaining messages
return (void*) status;
}
void startSync()
{
sync_queue.clear();
// status = attach_sync_session(i->session, i->sync_session);
// if(status != PEP_STATUS_OK)
// throw std::runtime_error("Cannot attach to sync session! status: " + status_to_string(status));
sync_thread.reset( new std::thread( syncThreadRoutine, nullptr ) );
}
void stopSync()
{
// No sync session active
if(sync_session == nullptr)
return;
sync_queue.push_front(NULL);
sync_thread->join();
unregister_sync_callbacks(sync_session);
sync_queue.clear();
pEp::call_with_lock(&release, sync_session);
sync_session = nullptr;
}
void startKeyserverLookup()
{
if(keyserver_lookup_session)
throw std::runtime_error("KeyserverLookup already started.");
PEP_STATUS status = pEp::call_with_lock(&init, &keyserver_lookup_session, &JsonAdapter::messageToSend, &injectSyncMsg);
if(status != PEP_STATUS_OK || keyserver_lookup_session==nullptr)
{
throw std::runtime_error("Cannot create keyserver lookup session! status: " + ::pEp::status_to_string(status));
}
keyserver_lookup_queue.clear();
status = register_examine_function(keyserver_lookup_session,
examineIdentity,
&keyserver_lookup_session // nullptr is not accepted, so any dummy ptr is used here
);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot register keyserver lookup callbacks! status: " + ::pEp::status_to_string(status));
keyserver_lookup_thread.reset( new std::thread( &keyserverLookupThreadRoutine, &keyserver_lookup_session /* just a dummy */ ) );
}
void stopKeyserverLookup()
{
// No keyserver lookup session active
if(keyserver_lookup_session == nullptr)
return;
keyserver_lookup_queue.push_front(NULL);
keyserver_lookup_thread->join();
// there is no unregister_examine_callback() function. hum...
keyserver_lookup_queue.clear();
pEp::call_with_lock(&release, keyserver_lookup_session);
keyserver_lookup_session = nullptr;
}
int examineIdentity(pEp_identity* idy, void* obj)
{
// JsonAdapter* ja = static_cast<JsonAdapter*>(obj);
return injectIdentity(idy);
}
void* keyserverLookupThreadRoutine(void* arg)
{
PEP_STATUS status = do_keymanagement(
&retrieveNextIdentity,
arg); // does the whole work
keyserver_lookup_queue.clear();
return (void*) status;
}
} // end of namespace pEp::mini
} // end of namespace pEp

@ -0,0 +1,34 @@
#ifndef MINI_ADAPTER_IMPL_HH
#define MINI_ADAPTER_IMPL_HH
#include <pEp/keymanagement.h>
#include <pEp/sync_api.h>
namespace pEp{
namespace mini {
int injectSyncMsg(Sync_event* msg, void* /*management*/ );
int injectIdentity(pEp_identity* idy);
Sync_event* retrieveNextSyncMsg(void* /*management*/, unsigned timeout);
pEp_identity* retrieveNextIdentity( void* /*management*/);
void* syncThreadRoutine(void* arg);
void startSync();
void stopSync();
void startKeyserverLookup();
void stopKeyserverLookup();
int examineIdentity(pEp_identity* idy, void* obj);
void* keyserverLookupThreadRoutine(void* arg);
} // end of namespace pEp::mini
} // end of namespace pEp
#endif // MINI_ADAPTER_IMPL_HH

@ -1,4 +1,6 @@
#include "main.hh"
#include "mini-adapter-impl.hh"
#include "ev_server.hh"
#include "prefix-config.hh"
#include "json-adapter.hh"
@ -12,6 +14,9 @@
#include <iostream>
#include <boost/program_options.hpp>
#include <pEp/call_with_lock.hh>
#include <pEp/status_to_string.hh>
namespace po = boost::program_options;
bool debug_mode = false;
@ -28,6 +33,10 @@ std::string logfile = "";
unsigned start_port = 4223;
unsigned end_port = 9999;
// albait not documented, the first PEP_SESSION in a process is special:
// It must be alive as long as any other PEP_SESSIONS are living.
static PEP_SESSION first_session = nullptr;
void print_version()
{
@ -41,6 +50,7 @@ void print_version()
std::ostream* my_logfile = nullptr;
std::shared_ptr<std::ostream> real_logfile;
int main(int argc, char** argv)
try
{
@ -112,9 +122,21 @@ try
if( debug_mode == false )
daemonize (!debug_mode, (const uintptr_t) status_handle);
JsonAdapter ja;
ja.do_sync( do_sync)
.ignore_session_errors( ignore_missing_session)
// create a dummy session just to see whether the Engine is functional.
// reason: here we still can log errors to stderr, because prepare_run() is called before daemonize().
PEP_STATUS status = pEp::call_with_lock(&init, &first_session, &JsonAdapter::messageToSend, &pEp::mini::injectSyncMsg);
if(status != PEP_STATUS_OK || first_session==nullptr)
{
const std::string error_msg = "Cannot create first session! PEP_STATUS: " + ::pEp::status_to_string(status) + ".";
std::cerr << error_msg << std::endl; // Log to stderr intentionally, so Enigmail can grab that error message easily.
if( ! ignore_missing_session)
{
throw std::runtime_error(error_msg);
}
}
JsonAdapter& ja = JsonAdapter::getInstance();
ja.ignore_session_errors( ignore_missing_session)
.deliver_html( !no_html )
;
/*
@ -145,7 +167,7 @@ try
}
ja.shutdown(nullptr);
ja.Log() << "Good bye. :-)";
JsonAdapter::global_shutdown();
pEp::call_with_lock(&release, first_session);
}
catch(std::exception const& e)
{

@ -1,6 +1,6 @@
#include "pep-types.hh"
#include "pep-utils.hh"
#include "pep-utils-json.hh"
#include "pEp-types.hh"
#include "pEp-utils.hh"
#include "pEp-utils-json.hh"
#include "json-adapter.hh"
#include <pEp/pEp_string.h>

@ -1,4 +1,4 @@
#include "pep-utils.hh"
#include "pEp-utils.hh"
#include <fstream>
#include <sstream>
#include <stdexcept>

@ -67,21 +67,21 @@ fs::path get_token_filename()
throw std::runtime_error("Cannot get home directory. $HOME environment variable is not set.");
}
const fs::path pep_dir = fs::path(home_dir) / ".pEp";
const fs::path pEp_dir = fs::path(home_dir) / ".pEp";
boost::system::error_code ec;
fs::create_directory( pep_dir, ec );
fs::create_directory( pEp_dir, ec );
if(ec)
{
throw boost::system::system_error(ec, "Cannot create pEp home directory" );
}
fs::permissions( pep_dir, fs::perms(0700), ec);
fs::permissions( pEp_dir, fs::perms(0700), ec);
if(ec)
{
throw boost::system::system_error(ec, "Cannot change permissions of pEp home directory to 0700 ");
}
return pep_dir / "json-token";
return pEp_dir / "json-token";
}

@ -3,7 +3,7 @@
#include <fstream>
#include <sstream>
#include "logger.hh"
#include "pep-utils-json.hh"
#include "pEp-utils-json.hh"
#include <pEp/pEpEngine.h> // for PEP_VERSION and get_engine_version()
#include <boost/algorithm/string/trim.hpp>
#include "json_spirit/json_spirit_reader.h"

@ -1,7 +1,7 @@
#include <gtest/gtest.h>
#include "inout.hh" // for to_json() and from_json()
#include "pep-types.hh"
#include "pEp-types.hh"
#include "json_spirit/json_spirit_writer.h"
#include "json_spirit/json_spirit_reader.h"
#include <pEp/message.h>
Loading…
Cancel
Save