// This file is under GNU General Public License 3.0 // see LICENSE.txt #include "Adapter.hh" #include #include #include #include "status_to_string.hh" #include "pEpLog.hh" #include "passphrase_cache.hh" using namespace std; thread_local pEp::Adapter::Session pEp::Adapter::session; namespace pEp { void throw_status(PEP_STATUS status) { if (status == PEP_STATUS_OK) return; if (status >= 0x400 && status <= 0x4ff) return; if (status == PEP_STATEMACHINE_CANNOT_SEND) return; if (status == PEP_OUT_OF_MEMORY) throw bad_alloc(); if (status == PEP_ILLEGAL_VALUE) throw invalid_argument("illegal value"); string _status = status_to_string(status); throw RuntimeError(_status, status); } RuntimeError::RuntimeError(const std::string& _text, PEP_STATUS _status) : std::runtime_error(_text.c_str()), text(_text), status(_status) { } namespace Adapter { messageToSend_t _messageToSend = nullptr; notifyHandshake_t _notifyHandshake = nullptr; std::thread _sync_thread; ::utility::locked_queue< SYNC_EVENT, ::free_Sync_event > q; std::mutex m; std::thread::id sync_thread_id() { return _sync_thread.get_id(); } int _inject_sync_event(SYNC_EVENT ev, void *management) { try { if (ev == nullptr) { q.clear(); q.push_back(ev); } else { q.push_front(ev); } } catch (exception&) { return 1; } return 0; } PEP_STATUS _ensure_passphrase(PEP_SESSION session, const char *fpr) { return passphrase_cache.ensure_passphrase(session, fpr); } // threshold: max waiting time in seconds SYNC_EVENT _retrieve_next_sync_event(void *management, unsigned threshold) { SYNC_EVENT syncEvent = nullptr; const bool success = q.try_pop_front(syncEvent, std::chrono::seconds(threshold)); if (!success) return new_sync_timeout_event(); return syncEvent; } bool on_sync_thread() { return _sync_thread.get_id() == this_thread::get_id(); } PEP_SESSION Session::operator()(session_action action) { std::lock_guard lock(m); bool in_sync = on_sync_thread(); PEP_STATUS status = PEP_STATUS_OK; switch (action) { case release: if (_session.get()) _session = nullptr; break; case init: if (!_session.get()) { PEP_SESSION session_; status = ::init(&session_, _messageToSend, _inject_sync_event, _ensure_passphrase); throw_status(status); _session = SessionPtr{session_, ::release}; } break; default: status = PEP_ILLEGAL_VALUE; } throw_status(status); return _session.get(); } void shutdown() { pEpLog("called"); if (_sync_thread.joinable()) { pEpLog("sync_is_running - injecting null event"); _inject_sync_event(nullptr, nullptr); _sync_thread.join(); } } bool is_sync_running() { return _sync_thread.joinable(); } bool in_shutdown() { SYNC_EVENT ev; try { ev = q.back(); } catch (std::underflow_error&) { return false; } if (ev) return false; else return true; } } }