#include "callback_dispatcher.hh" #include "passphrase_cache.hh" #include #include pEp::CallbackDispatcher pEp::callback_dispatcher; namespace pEp { PEP_STATUS CallbackDispatcher::messageToSend(::message *msg) { return callback_dispatcher._messageToSend(msg); } PEP_STATUS CallbackDispatcher::notifyHandshake(::pEp_identity *me, ::pEp_identity *partner, ::sync_handshake_signal signal) { return callback_dispatcher._notifyHandshake(me, partner, signal); } void CallbackDispatcher::add( ::messageToSend_t messageToSend, ::notifyHandshake_t notifyHandshake, proc on_startup, proc shutdown ) { assert(messageToSend); if (!messageToSend) throw std::invalid_argument("messageToSend must be set"); targets.push_back({messageToSend, notifyHandshake, on_startup, shutdown}); } void CallbackDispatcher::remove(::messageToSend_t messageToSend) { assert(messageToSend); if (!messageToSend) throw std::invalid_argument("messageToSend argument needed"); for (auto target = targets.begin(); target != targets.end(); ++target) { if (target->messageToSend == messageToSend) { targets.erase(target); break; } } if (targets.empty()) stop_sync(); } void CallbackDispatcher::on_startup() { for (auto target : targets) { if (target.on_startup) target.on_startup(); } } void CallbackDispatcher::on_shutdown() { for (auto target : targets) { if (target.on_shutdown) target.on_shutdown(); } } void CallbackDispatcher::start_sync() { callback_dispatcher.semaphore.go(); pEp::Adapter::startup(CallbackDispatcher::messageToSend, CallbackDispatcher::notifyHandshake, &callback_dispatcher, &CallbackDispatcher::on_startup, &CallbackDispatcher::on_shutdown); for (auto target : callback_dispatcher.targets) { if (target.notifyHandshake) target.notifyHandshake(nullptr, nullptr, SYNC_NOTIFY_START); } } void CallbackDispatcher::stop_sync() { callback_dispatcher.semaphore.stop(); Adapter::shutdown(); callback_dispatcher.semaphore.go(); for (auto target : callback_dispatcher.targets) { if (target.notifyHandshake) target.notifyHandshake(nullptr, nullptr, SYNC_NOTIFY_STOP); } } PEP_STATUS CallbackDispatcher::_messageToSend(::message *msg) { if (Adapter::on_sync_thread() && !msg) { semaphore.try_wait(); if (Adapter::in_shutdown()) return PEP_SYNC_NO_CHANNEL; PEP_STATUS status = PassphraseCache::config_next_passphrase(); // if the cache has no valid passphrase ask the app if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) semaphore.stop(); // the pEp engine must try again return status; } if (Adapter::on_sync_thread()) { // a passphrase worked, reset passphrase_cache iterator PassphraseCache::config_next_passphrase(true); } for (auto target : targets) { ::message *_msg = nullptr; if (msg) { _msg = ::message_dup(msg); if (!_msg) return PEP_OUT_OF_MEMORY; } assert(target.messageToSend); target.messageToSend(_msg); } return PEP_STATUS_OK; } PEP_STATUS CallbackDispatcher::_notifyHandshake(::pEp_identity *me, ::pEp_identity *partner, ::sync_handshake_signal signal) { for (auto target : targets) { if (target.notifyHandshake) { ::pEp_identity *_me = nullptr; if (me) { _me = ::identity_dup(me); if (!_me) return PEP_OUT_OF_MEMORY; } ::pEp_identity *_partner = nullptr; if (partner) { _partner = ::identity_dup(partner); if (!_partner) { free_identity(_me); return PEP_OUT_OF_MEMORY; } } target.notifyHandshake(_me, _partner, signal); } } return PEP_STATUS_OK; } };