diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..c893fb9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,39 @@ +# Generated from CLion C/C++ Code Style settings +BasedOnStyle: LLVM +Language: Cpp +DerivePointerAlignment: true +SortIncludes: false +ReflowComments: false +PointerAlignment: Left +AlignAfterOpenBracket: AlwaysBreak +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +ExperimentalAutoDetectBinPacking: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true +ColumnLimit: 100 +AllowAllConstructorInitializersOnNextLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +PenaltyBreakBeforeFirstCallParameter: 0 +PenaltyReturnTypeOnItsOwnLine: 1000000 +PenaltyBreakAssignment: 1000000 +PenaltyExcessCharacter: 10 +IndentCaseLabels: true +IndentWidth: 4 +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +SpaceAfterTemplateKeyword: false +AccessModifierOffset: -4 +AllowShortBlocksOnASingleLine: Always +IndentPPDirectives: BeforeHash \ No newline at end of file diff --git a/Makefile b/Makefile index 6eac3c6..58019c3 100644 --- a/Makefile +++ b/Makefile @@ -3,45 +3,22 @@ # This file may be used under the terms of the GNU General Public License version 3 # see LICENSE.txt -include Makefile.conf +.PHONY: src test install uninstall clean -TARGET=libpEpAdapter.a +all: src -.PHONY: install uninstall clean +src: + $(MAKE) -C src -SOURCE=$(wildcard *.cc) -HEADERS=$(wildcard *.hh *.hxx) -OBJECTS=$(subst .cc,.o,$(SOURCE)) -DEPENDS=$(subst .cc,.d,$(SOURCE)) -CXXFLAGS+= -MMD -MP - -all: $(TARGET) - -ifneq ($(MAKECMDGOALS),clean) - -include $(DEPENDS) -endif - -lib: $(TARGET) - -all: lib - -test: lib +test: src $(MAKE) -C test -$(TARGET): $(OBJECTS) - $(AR) -rc $@ $^ - clean: - rm -vf $(TARGET) $(OBJECTS) $(DEPENDS) - rm -f *.d.* + $(MAKE) -C src clean $(MAKE) -C test clean -install: $(TARGET) - mkdir -p $(PREFIX)/include/pEp - mkdir -p $(PREFIX)/lib - cp -v $(HEADERS) $(PREFIX)/include/pEp/ - cp -v $(TARGET) $(PREFIX)/lib/ +install: + $(MAKE) -C src install uninstall: - cd $(PREFIX)/include/pEp && rm -vf $(HEADERS) - cd $(PREFIX)/lib && rm -vf $(TARGET) + $(MAKE) -C src uninstall \ No newline at end of file diff --git a/Makefile.conf b/Makefile.conf index 107dd57..658919e 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -5,6 +5,7 @@ HERE:=$(dir $(lastword $(MAKEFILE_LIST))) +TARGET=libpEpAdapter.a # Defaults DEBUG=1 @@ -12,7 +13,7 @@ PREFIX?=$(HOME) ENGINE_LIB_PATH=$(PREFIX)/lib ENGINE_INC_PATH=$(PREFIX)/include -CXXFLAGS+=-std=c++11 -fPIC +CXXFLAGS+=-std=c++14 -fPIC # Build target BUILD_FOR:=$(shell uname) diff --git a/readme.md b/README.md similarity index 100% rename from readme.md rename to README.md diff --git a/call_with_lock.hh b/call_with_lock.hh deleted file mode 100644 index c8ebd73..0000000 --- a/call_with_lock.hh +++ /dev/null @@ -1,26 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#ifndef LIBPEPADAPTER_CALL_WITH_LOCK_HH -#define LIBPEPADAPTER_CALL_WITH_LOCK_HH - -#include - -namespace pEp -{ - extern std::mutex call_with_lock_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 - R call_with_lock( R(*fn)(Args...), Args... args) - { - std::lock_guard L(call_with_lock_mutex); - return fn(args...); - } - - -} - -#endif // LIBPEPADAPTER_CALL_WITH_LOCK_HH diff --git a/constant_time_algo.cc b/constant_time_algo.cc deleted file mode 100644 index 8368b9e..0000000 --- a/constant_time_algo.cc +++ /dev/null @@ -1,23 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#include "constant_time_algo.hh" - -namespace pEp -{ - bool constant_time_equal(const std::string& a, const std::string& b) - { - if(a.size() != b.size()) - return false; - - unsigned d = 0; - for(std::size_t idx = 0; idx(a[idx]) ^ static_cast(b[idx]) ); - } - - // if d is still 0, the strings are equal. - return d == 0; - } - -} // end of namespace pEp diff --git a/message_cache.hh b/message_cache.hh deleted file mode 100644 index b5c06be..0000000 --- a/message_cache.hh +++ /dev/null @@ -1,135 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#ifndef LIBPEPADAPTER_MESSAGE_CACHE_HH -#define LIBPEPADAPTER_MESSAGE_CACHE_HH - -#include -#include -#include -#include -#include - -namespace pEp { - class MessageCache { - struct cache_entry { - cache_entry(::message *s, ::message *d) - : src(s), dst(d) { } - - ::message *src; - ::message *dst; - }; - - using cache = std::unordered_map; - - cache _cache; - std::mutex _mtx; - long long id_range = 42; - long long next_id = 23; - - public: - MessageCache(); - - enum which { msg_src = 0, msg_dst = 1 }; - - static PEP_STATUS cache_mime_decode_message( - const char *mimetext, - size_t size, - message **msg, - bool* has_possible_pEp_msg - ); - - static PEP_STATUS cache_mime_encode_message( - int one, - const message * msg, - bool omit_fields, - char **mimetext, - bool has_pEp_msg_attachment - ); - - static PEP_STATUS cache_decrypt_message( - PEP_SESSION session, - message *src, - message **dst, - stringlist_t **keylist, - PEP_rating *rating, - PEP_decrypt_flags_t *flags - ); - - static PEP_STATUS cache_encrypt_message( - PEP_SESSION session, - message *src, - stringlist_t *extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ); - - static PEP_STATUS cache_encrypt_message_for_self( - PEP_SESSION session, - pEp_identity* target_id, - message *src, - stringlist_t* extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ); - - - static PEP_STATUS cache_release(std::string id); - static void removeCacheID(::message* msg); - - protected: - void release(std::string id); - - PEP_STATUS mime_decode_message( - const char *mimetext, - size_t size, - message **msg, - bool* has_possible_pEp_msg - ); - - PEP_STATUS mime_encode_message( - which one, - const message * src, - bool omit_fields, - char **mimetext, - bool has_pEp_msg_attachment - ); - - PEP_STATUS decrypt_message( - PEP_SESSION session, - message *src, - message **dst, - stringlist_t **keylist, - PEP_rating *rating, - PEP_decrypt_flags_t *flags - ); - - PEP_STATUS encrypt_message( - PEP_SESSION session, - message *src, - stringlist_t *extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ); - - PEP_STATUS encrypt_message_for_self( - PEP_SESSION session, - pEp_identity* target_id, - message *src, - stringlist_t* extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ); - - void generateCacheID(::message* msg); - static std::string cacheID(const ::message* msg); - }; - - extern MessageCache message_cache; -}; - -#endif // LIBPEPADAPTER_MESSAGE_CACHE_HH diff --git a/pEpLog.cc b/pEpLog.cc deleted file mode 100644 index 08af695..0000000 --- a/pEpLog.cc +++ /dev/null @@ -1,40 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#include "pEpLog.hh" -#include -#include -#include -#include - - -namespace pEp { -namespace Adapter { -namespace pEpLog { - -std::mutex mtx; - -std::atomic_bool is_enabled{false}; - -void set_enabled(bool enabled) { - is_enabled.store(enabled); -} - -bool get_enabled() { - return is_enabled.load(); -} - -void log(std::string msg) { - if (is_enabled.load()) { - std::lock_guard l(mtx); - #ifdef ANDROID - __android_log_print(ANDROID_LOG_DEBUG, "pEpDebugLog", "%s", msg.c_str()); - #else - std::cout << msg << std::endl; //std::endl also flushes - #endif - } -} - -} // pEpLog -} // Adapter -} // pEp diff --git a/slurp.cc b/slurp.cc deleted file mode 100644 index a5cb3c5..0000000 --- a/slurp.cc +++ /dev/null @@ -1,25 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#include "slurp.hh" -#include -#include -#include - -namespace pEp -{ - -std::string slurp(const std::string& filename) -{ - std::ifstream input(filename.c_str(), std::ios_base::binary); - if(!input) - { - throw std::runtime_error("Cannot read file \"" + filename + "\"! "); - } - - std::stringstream sstr; - sstr << input.rdbuf(); - return sstr.str(); -} - -} // end of namespace pEp diff --git a/Adapter.cc b/src/Adapter.cc similarity index 64% rename from Adapter.cc rename to src/Adapter.cc index dfcaef9..baf0254 100644 --- a/Adapter.cc +++ b/src/Adapter.cc @@ -14,35 +14,39 @@ using namespace std; thread_local pEp::Adapter::Session pEp::Adapter::session; namespace pEp { - void throw_status(PEP_STATUS status) + void throw_status(::PEP_STATUS status) { - if (status == PEP_STATUS_OK) + if (status == ::PEP_STATUS_OK) { return; - if (status >= 0x400 && status <= 0x4ff) + } + if (status >= 0x400 && status <= 0x4ff) { return; - if (status == PEP_STATEMACHINE_CANNOT_SEND) + } + if (status == ::PEP_STATEMACHINE_CANNOT_SEND) { return; - if (status == PEP_OUT_OF_MEMORY) + } + if (status == ::PEP_OUT_OF_MEMORY) { throw bad_alloc(); - if (status == PEP_ILLEGAL_VALUE) + } + if (status == ::PEP_ILLEGAL_VALUE) { throw invalid_argument("illegal value"); + } - string _status = status_to_string(status); + 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) + 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; + ::messageToSend_t _messageToSend = nullptr; + ::notifyHandshake_t _notifyHandshake = nullptr; std::thread _sync_thread; - ::utility::locked_queue< SYNC_EVENT, ::free_Sync_event > sync_evt_q; + ::utility::locked_queue sync_evt_q; std::mutex m; std::thread::id sync_thread_id() @@ -50,36 +54,34 @@ namespace pEp { return _sync_thread.get_id(); } - int _inject_sync_event(SYNC_EVENT ev, void *management) + int _inject_sync_event(::SYNC_EVENT ev, void *management) { try { if (ev == nullptr) { sync_evt_q.clear(); sync_evt_q.push_back(ev); - } - else { + } else { sync_evt_q.push_front(ev); } - } - catch (exception&) { + } catch (exception &) { return 1; } return 0; } - PEP_STATUS _ensure_passphrase(PEP_SESSION session, const char *fpr) + 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 _retrieve_next_sync_event(void *management, unsigned threshold) { - SYNC_EVENT syncEvent = nullptr; + ::SYNC_EVENT syncEvent = nullptr; const bool success = sync_evt_q.try_pop_front(syncEvent, std::chrono::seconds(threshold)); if (!success) { - return new_sync_timeout_event(); + return ::new_sync_timeout_event(); } return syncEvent; @@ -90,11 +92,11 @@ namespace pEp { return _sync_thread.get_id() == this_thread::get_id(); } - PEP_SESSION Session::operator()(session_action action) + ::PEP_SESSION Session::operator()(session_action action) { std::lock_guard lock(m); - PEP_STATUS status = PEP_STATUS_OK; + ::PEP_STATUS status = ::PEP_STATUS_OK; switch (action) { case release: @@ -105,7 +107,7 @@ namespace pEp { case init: if (!_session.get()) { - PEP_SESSION session_; + ::PEP_SESSION session_; status = ::init(&session_, _messageToSend, _inject_sync_event, _ensure_passphrase); throw_status(status); _session = SessionPtr{session_, ::release}; @@ -113,7 +115,7 @@ namespace pEp { break; default: - status = PEP_ILLEGAL_VALUE; + status = ::PEP_ILLEGAL_VALUE; } throw_status(status); @@ -122,9 +124,9 @@ namespace pEp { void shutdown() { - pEpLog("called"); + pEpLog("called"); if (_sync_thread.joinable()) { - pEpLog("sync_is_running - injecting null event"); + pEpLog("sync_is_running - injecting null event"); _inject_sync_event(nullptr, nullptr); _sync_thread.join(); } @@ -140,8 +142,7 @@ namespace pEp { SYNC_EVENT ev; try { ev = sync_evt_q.back(); - } - catch (std::underflow_error&) { + } catch (std::underflow_error &) { return false; } if (ev) { @@ -149,6 +150,6 @@ namespace pEp { } else { return true; } - } - } -} + } + } // namespace Adapter +} // namespace pEp diff --git a/Adapter.hh b/src/Adapter.hh similarity index 71% rename from Adapter.hh rename to src/Adapter.hh index 43f0f0c..b02252e 100644 --- a/Adapter.hh +++ b/src/Adapter.hh @@ -5,10 +5,10 @@ #define LIBPEPADAPTER_ADAPTER_HH #include +#include +#include #include #include -#include -#include #include @@ -17,26 +17,25 @@ namespace pEp { // throws std::bad_alloc if status==PEP_OUT_OF_MEMORY, // throws std::invalid_argument if status==PEP_ILLEGAL_VALUE, // throws RuntimeError when 'status' represents another exceptional value. - void throw_status(PEP_STATUS status); + void throw_status(::PEP_STATUS status); struct RuntimeError : std::runtime_error { - RuntimeError(const std::string& _text, PEP_STATUS _status); + RuntimeError(const std::string &_text, ::PEP_STATUS _status); std::string text; - PEP_STATUS status; + ::PEP_STATUS status; }; namespace Adapter { - int _inject_sync_event(SYNC_EVENT ev, void *management); - PEP_STATUS _ensure_passphrase(PEP_SESSION session, const char *fpr); + int _inject_sync_event(::SYNC_EVENT ev, void *management); + ::PEP_STATUS _ensure_passphrase(::PEP_SESSION session, const char *fpr); template void startup( messageToSend_t messageToSend, notifyHandshake_t notifyHandshake, T *obj = nullptr, - std::function< void (T *) > _startup = nullptr, - std::function< void (T *) > _shutdown = nullptr - ); + std::function _startup = nullptr, + std::function _shutdown = nullptr); // returns 'true' when called from the "sync" thread, 'false' otherwise. bool on_sync_thread(); @@ -44,7 +43,8 @@ namespace pEp { // returns the thread id of the sync thread std::thread::id sync_thread_id(); - enum session_action { + enum session_action + { init, release }; @@ -59,15 +59,15 @@ namespace pEp { extern thread_local Session session; - // injects a NULL event into sync_event_queue to denote sync thread to shutdown, - // and joins & removes the sync thread + // injects a NULL event into sync_event_queue to denote sync thread to + // shutdown, and joins & removes the sync thread void shutdown(); bool is_sync_running(); bool in_shutdown(); - } -} + } // namespace Adapter +} // namespace pEp #include "Adapter.hxx" -#endif //LIBPEPADAPTER_ADAPTER_HH \ No newline at end of file +#endif // LIBPEPADAPTER_ADAPTER_HH \ No newline at end of file diff --git a/Adapter.hxx b/src/Adapter.hxx similarity index 72% rename from Adapter.hxx rename to src/Adapter.hxx index 2b8b054..30cfce5 100644 --- a/Adapter.hxx +++ b/src/Adapter.hxx @@ -14,20 +14,20 @@ namespace pEp { namespace Adapter { using std::function; - extern messageToSend_t _messageToSend; - extern notifyHandshake_t _notifyHandshake; + extern ::messageToSend_t _messageToSend; + extern ::notifyHandshake_t _notifyHandshake; extern std::thread _sync_thread; - extern ::utility::locked_queue< SYNC_EVENT, ::free_Sync_event > sync_evt_q; + extern ::utility::locked_queue<::SYNC_EVENT, ::free_Sync_event> sync_evt_q; extern std::mutex m; - SYNC_EVENT _retrieve_next_sync_event(void *management, unsigned threshold); + ::SYNC_EVENT _retrieve_next_sync_event(void *management, unsigned threshold); static std::exception_ptr _ex; static std::atomic_bool register_done{false}; - template< class T > - void sync_thread(T *obj, function< void(T *) > _startup, function< void(T *) > _shutdown) + template + void sync_thread(T *obj, function _startup, function _shutdown) { pEpLog("called"); _ex = nullptr; @@ -41,16 +41,19 @@ namespace pEp { session(); { - //TODO: Do we need to use a passphraseWrap here??? + // TODO: Do we need to use a passphraseWrap here??? pEpLog("register_sync_callbacks()"); - PEP_STATUS status = register_sync_callbacks(session(), nullptr, - _notifyHandshake, _retrieve_next_sync_event); + ::PEP_STATUS status = ::register_sync_callbacks( + session(), + nullptr, + _notifyHandshake, + _retrieve_next_sync_event); + pEpLog("register_sync_callbacks() return:" << status); try { throw_status(status); register_done.store(true); - } - catch (...) { + } catch (...) { _ex = std::current_exception(); register_done.store(true); return; @@ -58,7 +61,7 @@ namespace pEp { } pEpLog("sync protocol loop started"); - do_sync_protocol(session(), (void *)obj); + ::do_sync_protocol(session(), (void *)obj); pEpLog("sync protocol loop ended"); unregister_sync_callbacks(session()); @@ -69,13 +72,13 @@ namespace pEp { } } - template< class T > + template void startup( messageToSend_t messageToSend, notifyHandshake_t notifyHandshake, T *obj, - function< void(T *) > _startup, - function< void(T *) > _shutdown) + function _startup, + function _shutdown) { pEpLog("called"); if (messageToSend) { @@ -104,7 +107,7 @@ namespace pEp { } } } - } -} + } // namespace Adapter +} // namespace pEp -#endif //LIBPEPADAPTER_ADAPTER_HXX \ No newline at end of file +#endif // LIBPEPADAPTER_ADAPTER_HXX \ No newline at end of file diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..2b3b74b --- /dev/null +++ b/src/Makefile @@ -0,0 +1,37 @@ +# Copyright 2018, pEp Foundation +# This file is part of lib pEp Adapter +# This file may be used under the terms of the GNU General Public License version 3 +# see LICENSE.txt + +include ../Makefile.conf + +SOURCE=$(wildcard *.cc) +HEADERS=$(wildcard *.hh *.hxx) +OBJECTS=$(subst .cc,.o,$(SOURCE)) +DEPENDS=$(subst .cc,.d,$(SOURCE)) +CXXFLAGS+= -MMD -MP + +ifneq ($(MAKECMDGOALS),clean) + -include $(DEPENDS) +endif + +.PHONY: install uninstall clean + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(AR) -rc $@ $^ + +clean: + rm -vf $(TARGET) $(OBJECTS) $(DEPENDS) + rm -f *.d.* + +install: $(TARGET) + mkdir -p $(PREFIX)/include/pEp + mkdir -p $(PREFIX)/lib + cp -v $(HEADERS) $(PREFIX)/include/pEp/ + cp -v $(TARGET) $(PREFIX)/lib/ + +uninstall: + cd $(PREFIX)/include/pEp && rm -vf $(HEADERS) + cd $(PREFIX)/lib && rm -vf $(TARGET) diff --git a/Semaphore.hh b/src/Semaphore.hh similarity index 92% rename from Semaphore.hh rename to src/Semaphore.hh index a9c0593..c026185 100644 --- a/Semaphore.hh +++ b/src/Semaphore.hh @@ -19,7 +19,7 @@ namespace pEp { std::atomic_bool _stop; public: - Semaphore() : _stop(false) { } + Semaphore() : _stop(false) {} void stop() { @@ -34,7 +34,7 @@ namespace pEp { return; } - while(_stop.load()) { + while (_stop.load()) { cv.wait(lock); } } @@ -46,8 +46,6 @@ namespace pEp { cv.notify_all(); } }; -} +} // namespace pEp #endif // LIBPEPADAPTER_SEMAPHORE_HH - - diff --git a/call_with_lock.cc b/src/call_with_lock.cc similarity index 66% rename from call_with_lock.cc rename to src/call_with_lock.cc index 83ba416..82a9c49 100644 --- a/call_with_lock.cc +++ b/src/call_with_lock.cc @@ -3,7 +3,6 @@ #include "call_with_lock.hh" -namespace pEp -{ - std::mutex call_with_lock_mutex; +namespace pEp { + std::mutex call_with_lock_mutex; } diff --git a/src/call_with_lock.hh b/src/call_with_lock.hh new file mode 100644 index 0000000..7e38dae --- /dev/null +++ b/src/call_with_lock.hh @@ -0,0 +1,26 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef LIBPEPADAPTER_CALL_WITH_LOCK_HH +#define LIBPEPADAPTER_CALL_WITH_LOCK_HH + +#include + +namespace pEp { + extern std::mutex call_with_lock_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 + R call_with_lock(R (*fn)(Args...), Args... args) + { + std::lock_guard L(call_with_lock_mutex); + return fn(args...); + } + + +} // namespace pEp + +#endif // LIBPEPADAPTER_CALL_WITH_LOCK_HH diff --git a/callback_dispatcher.cc b/src/callback_dispatcher.cc similarity index 85% rename from callback_dispatcher.cc rename to src/callback_dispatcher.cc index 42a743c..7a50dbc 100644 --- a/callback_dispatcher.cc +++ b/src/callback_dispatcher.cc @@ -14,18 +14,19 @@ namespace pEp { return callback_dispatcher._messageToSend(msg); } - PEP_STATUS CallbackDispatcher::notifyHandshake(::pEp_identity *me, - ::pEp_identity *partner, ::sync_handshake_signal signal) + 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 - ) + ::messageToSend_t messageToSend, + ::notifyHandshake_t notifyHandshake, + proc on_startup, + proc shutdown) { assert(messageToSend); if (!messageToSend) { @@ -77,10 +78,12 @@ namespace pEp { pEpLog("called"); callback_dispatcher.semaphore.go(); - pEp::Adapter::startup(CallbackDispatcher::messageToSend, - CallbackDispatcher::notifyHandshake, &callback_dispatcher, - &CallbackDispatcher::on_startup, - &CallbackDispatcher::on_shutdown); + pEp::Adapter::startup( + CallbackDispatcher::messageToSend, + CallbackDispatcher::notifyHandshake, + &callback_dispatcher, + &CallbackDispatcher::on_startup, + &CallbackDispatcher::on_shutdown); pEpLog("all targets signal: SYNC_NOTIFY_START"); for (auto target : callback_dispatcher.targets) { @@ -143,8 +146,10 @@ namespace pEp { return PEP_STATUS_OK; } - PEP_STATUS CallbackDispatcher::_notifyHandshake(::pEp_identity *me, - ::pEp_identity *partner, ::sync_handshake_signal signal) + PEP_STATUS CallbackDispatcher::_notifyHandshake( + ::pEp_identity *me, + ::pEp_identity *partner, + ::sync_handshake_signal signal) { for (auto target : targets) { if (target.notifyHandshake) { @@ -169,5 +174,4 @@ namespace pEp { return PEP_STATUS_OK; } -}; - +}; // namespace pEp diff --git a/callback_dispatcher.hh b/src/callback_dispatcher.hh similarity index 90% rename from callback_dispatcher.hh rename to src/callback_dispatcher.hh index 54248cf..5a75e29 100644 --- a/callback_dispatcher.hh +++ b/src/callback_dispatcher.hh @@ -34,8 +34,7 @@ namespace pEp { ::messageToSend_t messageToSend, ::notifyHandshake_t notifyHandshake, proc on_startup = nullptr, - proc on_shutdown = nullptr - ); + proc on_shutdown = nullptr); void remove(::messageToSend_t messageToSend); static void start_sync(); @@ -45,8 +44,8 @@ namespace pEp { static PEP_STATUS notifyHandshake( ::pEp_identity *me, ::pEp_identity *partner, - ::sync_handshake_signal signal - ); + ::sync_handshake_signal signal); + protected: void on_startup(); void on_shutdown(); @@ -55,13 +54,12 @@ namespace pEp { PEP_STATUS _notifyHandshake( ::pEp_identity *me, ::pEp_identity *partner, - ::sync_handshake_signal signal - ); + ::sync_handshake_signal signal); - friend const char *PassphraseCache::add(const std::string& passphrase); + friend const char *PassphraseCache::add(const std::string &passphrase); }; extern CallbackDispatcher callback_dispatcher; -} +} // namespace pEp #endif // LIBPEPADAPTER_CALLBACK_DISPATCHER_HH diff --git a/src/constant_time_algo.cc b/src/constant_time_algo.cc new file mode 100644 index 0000000..582cf0e --- /dev/null +++ b/src/constant_time_algo.cc @@ -0,0 +1,21 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "constant_time_algo.hh" + +namespace pEp { + bool constant_time_equal(const std::string &a, const std::string &b) + { + if (a.size() != b.size()) + return false; + + unsigned d = 0; + for (std::size_t idx = 0; idx < a.size(); ++idx) { + d |= (static_cast(a[idx]) ^ static_cast(b[idx])); + } + + // if d is still 0, the strings are equal. + return d == 0; + } + +} // end of namespace pEp diff --git a/constant_time_algo.hh b/src/constant_time_algo.hh similarity index 86% rename from constant_time_algo.hh rename to src/constant_time_algo.hh index 59463ac..c9e5733 100644 --- a/constant_time_algo.hh +++ b/src/constant_time_algo.hh @@ -6,14 +6,13 @@ #include -namespace pEp -{ +namespace pEp { // Returns false if a.size() != b.size(). // Compares always _all_ characters of 'a' and 'b' so runtime does not // depends on the character position where the strings differ. // Use this function instead of operator== if timing sidechannel attack // might be a security problem. - bool constant_time_equal(const std::string& a, const std::string& b); + bool constant_time_equal(const std::string &a, const std::string &b); } // end of namespace pEp diff --git a/locked_queue.hh b/src/locked_queue.hh similarity index 83% rename from locked_queue.hh rename to src/locked_queue.hh index e440704..008ecdd 100644 --- a/locked_queue.hh +++ b/src/locked_queue.hh @@ -8,17 +8,15 @@ #include #include -namespace utility -{ - template - class locked_queue - { - typedef std::recursive_mutex Mutex; - typedef std::unique_lock Lock; - - int _waiting = 0; - Mutex _mtx; - std::condition_variable_any _cv; +namespace utility { + template + class locked_queue { + typedef std::recursive_mutex Mutex; + typedef std::unique_lock Lock; + + int _waiting = 0; + Mutex _mtx; + std::condition_variable_any _cv; std::deque _q; public: @@ -30,10 +28,8 @@ namespace utility void clear() { Lock L(_mtx); - if(Deleter != nullptr) - { - for(auto q : _q) - { + if (Deleter != nullptr) { + for (auto q : _q) { Deleter(q); } } @@ -63,7 +59,7 @@ namespace utility T pop_back() { Lock L(_mtx); - _cv.wait(L, [&]{ return !_q.empty(); } ); + _cv.wait(L, [&] { return !_q.empty(); }); T r{std::move(_q.back())}; _q.pop_back(); return r; @@ -74,7 +70,7 @@ namespace utility T pop_front() { Lock L(_mtx); - _cv.wait(L, [&]{ return !_q.empty(); } ); + _cv.wait(L, [&] { return !_q.empty(); }); T r{std::move(_q.front())}; _q.pop_front(); return r; @@ -86,30 +82,28 @@ namespace utility { Lock L(_mtx); ++_waiting; - if(! _cv.wait_until(L, end_time, [this]{ return !_q.empty(); } ) ) - { + if (!_cv.wait_until(L, end_time, [this] { return !_q.empty(); })) { --_waiting; return false; } - + --_waiting; out = std::move(_q.back()); _q.pop_back(); return true; } - + // returns true and set a copy of the first element and pop it from queue if there is any // returns false and leaves 'out' untouched if queue is empty even after 'end_time' bool try_pop_front(T& out, std::chrono::steady_clock::time_point end_time) { Lock L(_mtx); ++_waiting; - if(! _cv.wait_until(L, end_time, [this]{ return !_q.empty(); } ) ) - { + if (!_cv.wait_until(L, end_time, [this] { return !_q.empty(); })) { --_waiting; return false; } - + --_waiting; out = std::move(_q.front()); _q.pop_front(); @@ -122,12 +116,11 @@ namespace utility { Lock L(_mtx); ++_waiting; - if(! _cv.wait_for(L, duration, [this]{ return !_q.empty(); } ) ) - { + if (!_cv.wait_for(L, duration, [this] { return !_q.empty(); })) { --_waiting; return false; } - + --_waiting; out = std::move(_q.front()); _q.pop_front(); diff --git a/message_cache.cc b/src/message_cache.cc similarity index 70% rename from message_cache.cc rename to src/message_cache.cc index f507253..b8cfaf3 100644 --- a/message_cache.cc +++ b/src/message_cache.cc @@ -20,67 +20,58 @@ namespace pEp { } PEP_STATUS MessageCache::cache_decrypt_message( - PEP_SESSION session, - message *src, - message **dst, - stringlist_t **keylist, - PEP_rating *rating, - PEP_decrypt_flags_t *flags - ) + PEP_SESSION session, + message *src, + message **dst, + stringlist_t **keylist, + PEP_rating *rating, + PEP_decrypt_flags_t *flags) { - return message_cache.decrypt_message(session, src, dst, keylist, - rating, flags); + return message_cache.decrypt_message(session, src, dst, keylist, rating, flags); } PEP_STATUS MessageCache::cache_mime_encode_message( - int one, - const message * msg, - bool omit_fields, - char **mimetext, - bool has_pEp_msg_attachment - ) + int one, + const message *msg, + bool omit_fields, + char **mimetext, + bool has_pEp_msg_attachment) { - which _one = (which) one; - return message_cache.mime_encode_message(_one, msg, omit_fields, - mimetext, has_pEp_msg_attachment); + which _one = (which)one; + return message_cache.mime_encode_message(_one, msg, omit_fields, mimetext, has_pEp_msg_attachment); } PEP_STATUS MessageCache::cache_mime_decode_message( - const char *mimetext, - size_t size, - message **msg, - bool* has_possible_pEp_msg - ) + const char *mimetext, + size_t size, + message **msg, + bool *has_possible_pEp_msg) { - return message_cache.mime_decode_message(mimetext, size, msg, - has_possible_pEp_msg); + return message_cache.mime_decode_message(mimetext, size, msg, has_possible_pEp_msg); } PEP_STATUS MessageCache::cache_encrypt_message( - PEP_SESSION session, - message *src, - stringlist_t *extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ) + PEP_SESSION session, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags) { - return message_cache.encrypt_message(session, src, extra, dst, - enc_format, flags); + return message_cache.encrypt_message(session, src, extra, dst, enc_format, flags); } PEP_STATUS MessageCache::cache_encrypt_message_for_self( - PEP_SESSION session, - pEp_identity* target_id, - message *src, - stringlist_t* extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ) + PEP_SESSION session, + pEp_identity *target_id, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags) { - return message_cache.encrypt_message_for_self(session, target_id, src, - extra, dst, enc_format, flags); + return message_cache + .encrypt_message_for_self(session, target_id, src, extra, dst, enc_format, flags); } PEP_STATUS MessageCache::cache_release(std::string id) @@ -96,8 +87,8 @@ namespace pEp { ::free_message(_cache.at(id).src); ::free_message(_cache.at(id).dst); _cache.erase(id); + } catch (...) { } - catch (...) { } } static char *dup(const char *src) @@ -105,7 +96,7 @@ namespace pEp { if (!src) return nullptr; - char * dst = ::strdup(src); + char *dst = ::strdup(src); assert(dst); if (!dst) throw std::bad_alloc(); @@ -118,7 +109,7 @@ namespace pEp { if (!src) return nullptr; - ::timestamp * dst = ::timestamp_dup(src); + ::timestamp *dst = ::timestamp_dup(src); if (!dst) throw std::bad_alloc(); @@ -130,7 +121,7 @@ namespace pEp { if (!src) return nullptr; - ::pEp_identity * dst = ::identity_dup(src); + ::pEp_identity *dst = ::identity_dup(src); if (!dst) throw std::bad_alloc(); @@ -142,7 +133,7 @@ namespace pEp { if (!src) return nullptr; - ::identity_list * dst = ::identity_list_dup(src); + ::identity_list *dst = ::identity_list_dup(src); if (!dst) throw std::bad_alloc(); @@ -154,7 +145,7 @@ namespace pEp { if (!src) return nullptr; - ::stringlist_t * dst = ::stringlist_dup(src); + ::stringlist_t *dst = ::stringlist_dup(src); if (!dst) throw std::bad_alloc(); @@ -166,19 +157,19 @@ namespace pEp { if (!src) return nullptr; - ::stringpair_list_t * dst = ::stringpair_list_dup(src); + ::stringpair_list_t *dst = ::stringpair_list_dup(src); if (!dst) throw std::bad_alloc(); return dst; } - static ::message_ref_list *dup(const ::message_ref_list *src) { + static ::message_ref_list *dup(const ::message_ref_list *src) + { if (!src) return nullptr; - ::message_ref_list *dst = (::message_ref_list *) ::calloc(1, - sizeof(::message_ref_list)); + ::message_ref_list *dst = (::message_ref_list *)::calloc(1, sizeof(::message_ref_list)); assert(dst); if (!dst) throw std::bad_alloc(); @@ -187,8 +178,7 @@ namespace pEp { for (const message_ref_list *s = src; s; s = s->next) { d->msg_ref = s->msg_ref; if (s->next) { - d->next = (::message_ref_list *) ::calloc(1, - sizeof(::message_ref_list)); + d->next = (::message_ref_list *)::calloc(1, sizeof(::message_ref_list)); assert(d); if (!d) throw std::bad_alloc(); @@ -223,7 +213,7 @@ namespace pEp { dst->longmsg = dup("pEp"); else if (!emptystr(src->longmsg_formatted)) dst->longmsg_formatted = dup(""); - + // attachments are never copied dst->rawmsg_ref = src->rawmsg_ref; @@ -251,9 +241,9 @@ namespace pEp { if (_id == "") { dst->opt_fields = dup(src->opt_fields); - } - else { - dst->opt_fields = ::new_stringpair_list(::new_stringpair("X-pEp-Adapter-Cache-ID", _id.c_str())); + } else { + dst->opt_fields = ::new_stringpair_list( + ::new_stringpair("X-pEp-Adapter-Cache-ID", _id.c_str())); if (!dst->opt_fields) throw std::bad_alloc(); dst->opt_fields->next = dup(src->opt_fields); @@ -262,20 +252,19 @@ namespace pEp { return dst; } - static void correctAttachmentsOrder(bloblist_t*& bl) + static void correctAttachmentsOrder(bloblist_t *&bl) { // only execute if there are exactly two attachments, both with // a non-empty MIME type if (bl && bl->next && !bl->next->next && !emptystr(bl->mime_type) && - !emptystr(bl->next->mime_type)) { + !emptystr(bl->next->mime_type)) { // if this is most likely an PGP/MIME compliant format then correct // order of attachments if (std::string(bl->mime_type) == "application/octet-stream" && - std::string(bl->next->mime_type) == - "application/pgp-encrypted") { + std::string(bl->next->mime_type) == "application/pgp-encrypted") { bloblist_t *one = bl->next; bloblist_t *two = bl; bl = one; @@ -285,7 +274,7 @@ namespace pEp { } } - static void swapContent(::message*& part, ::message*& full) + static void swapContent(::message *&part, ::message *&full) { free(part->longmsg); part->longmsg = full->longmsg; @@ -301,13 +290,12 @@ namespace pEp { } PEP_STATUS MessageCache::decrypt_message( - PEP_SESSION session, - message *src, - message **dst, - stringlist_t **keylist, - PEP_rating *rating, - PEP_decrypt_flags_t *flags - ) + PEP_SESSION session, + message *src, + message **dst, + stringlist_t **keylist, + PEP_rating *rating, + PEP_decrypt_flags_t *flags) { if (!src || cacheID(src) == "") return PEP_ILLEGAL_VALUE; @@ -324,8 +312,7 @@ namespace pEp { correctAttachmentsOrder(src->attachments); ::message *_dst = nullptr; - PEP_STATUS status = ::decrypt_message(session, src, &_dst, keylist, - rating, flags); + PEP_STATUS status = ::decrypt_message(session, src, &_dst, keylist, rating, flags); *dst = empty_message_copy(_dst, _id); { @@ -338,12 +325,11 @@ namespace pEp { } PEP_STATUS MessageCache::mime_encode_message( - which one, - const message * msg, - bool omit_fields, - char **mimetext, - bool has_pEp_msg_attachment - ) + which one, + const message *msg, + bool omit_fields, + char **mimetext, + bool has_pEp_msg_attachment) { if (!msg || cacheID(msg) == "") return PEP_ILLEGAL_VALUE; @@ -357,16 +343,14 @@ namespace pEp { std::lock_guard l(_mtx); ::message *_src = _cache.at(cacheID(msg)).src; swapContent(_msg, _src); - } - else /* msg_dst */ { + } else /* msg_dst */ { std::lock_guard l(_mtx); ::message *_dst = _cache.at(cacheID(msg)).dst; swapContent(_msg, _dst); } removeCacheID(_msg); - PEP_STATUS status = ::mime_encode_message(_msg, omit_fields, mimetext, - has_pEp_msg_attachment); + PEP_STATUS status = ::mime_encode_message(_msg, omit_fields, mimetext, has_pEp_msg_attachment); ::free_message(_msg); cache_release(cacheID(msg)); @@ -374,7 +358,7 @@ namespace pEp { return status; } - void MessageCache::generateCacheID(::message* msg) + void MessageCache::generateCacheID(::message *msg) { std::string _range = std::to_string(id_range); std::string _id = std::to_string(next_id++); @@ -383,18 +367,15 @@ namespace pEp { // if opt_fields is an empty list generate a new list if (!msg->opt_fields || !msg->opt_fields->value) { free_stringpair_list(msg->opt_fields); - msg->opt_fields = - ::new_stringpair_list(::new_stringpair("X-pEp-Adapter-Cache-ID", - cid.c_str())); + msg->opt_fields = ::new_stringpair_list( + ::new_stringpair("X-pEp-Adapter-Cache-ID", cid.c_str())); if (!msg->opt_fields) throw std::bad_alloc(); - } - else { + } else { // add the cache ID as first field to an existing list auto spl = msg->opt_fields; - msg->opt_fields = - ::new_stringpair_list(::new_stringpair("X-pEp-Adapter-Cache-ID", - cid.c_str())); + msg->opt_fields = ::new_stringpair_list( + ::new_stringpair("X-pEp-Adapter-Cache-ID", cid.c_str())); if (!msg->opt_fields) { msg->opt_fields = spl; throw std::bad_alloc(); @@ -403,12 +384,11 @@ namespace pEp { } } - std::string MessageCache::cacheID(const ::message* msg) + std::string MessageCache::cacheID(const ::message *msg) { for (auto spl = msg->opt_fields; spl && spl->value; spl = spl->next) { assert(spl->value->key); - if (spl->value->key && std::string(spl->value->key) == - "X-pEp-Adapter-Cache-ID") { + if (spl->value->key && std::string(spl->value->key) == "X-pEp-Adapter-Cache-ID") { assert(spl->value->value); if (spl->value->value) return spl->value->value; @@ -418,27 +398,22 @@ namespace pEp { } return ""; } - - void MessageCache::removeCacheID(::message* msg) + + void MessageCache::removeCacheID(::message *msg) { // if the first element in the list is the cache ID then skip - if (msg->opt_fields && msg->opt_fields->value && - msg->opt_fields->value->key && - std::string(msg->opt_fields->value->key) == - "X-pEp-Adapter-Cache-ID") { + if (msg->opt_fields && msg->opt_fields->value && msg->opt_fields->value->key && + std::string(msg->opt_fields->value->key) == "X-pEp-Adapter-Cache-ID") { auto n = msg->opt_fields->next; msg->opt_fields->next = nullptr; ::free_stringpair_list(msg->opt_fields); msg->opt_fields = n; - } - else { + } else { // go through the list and remove ::stringpair_list_t *prev = nullptr; - for (auto spl = msg->opt_fields; spl && spl->value; spl = - spl->next) { + for (auto spl = msg->opt_fields; spl && spl->value; spl = spl->next) { assert(spl->value->key); - if (spl->value->key && - std::string(spl->value->key) == "X-pEp-Adapter-Cache-ID") { + if (spl->value->key && std::string(spl->value->key) == "X-pEp-Adapter-Cache-ID") { auto next = spl->next; spl->next = nullptr; ::free_stringpair_list(spl); @@ -451,37 +426,34 @@ namespace pEp { } PEP_STATUS MessageCache::mime_decode_message( - const char *mimetext, - size_t size, - message **msg, - bool* has_possible_pEp_msg - ) + const char *mimetext, + size_t size, + message **msg, + bool *has_possible_pEp_msg) { ::message *_msg = nullptr; - PEP_STATUS status = ::mime_decode_message(mimetext, size, &_msg, - has_possible_pEp_msg); + PEP_STATUS status = ::mime_decode_message(mimetext, size, &_msg, has_possible_pEp_msg); if (status) return status; - generateCacheID(_msg); *msg = empty_message_copy(_msg); + generateCacheID(_msg); + *msg = empty_message_copy(_msg); { std::lock_guard l(_mtx); - message_cache._cache.emplace(std::make_pair(cacheID(_msg), - cache_entry(_msg, nullptr))); + message_cache._cache.emplace(std::make_pair(cacheID(_msg), cache_entry(_msg, nullptr))); } return status; } PEP_STATUS MessageCache::encrypt_message( - PEP_SESSION session, - message *src, - stringlist_t *extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ) + PEP_SESSION session, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags) { ::message *_msg; std::string _id = cacheID(src); @@ -492,8 +464,7 @@ namespace pEp { } ::message *_dst = nullptr; - PEP_STATUS status = ::encrypt_message(session, src, extra, &_dst, - enc_format, flags); + PEP_STATUS status = ::encrypt_message(session, src, extra, &_dst, enc_format, flags); *dst = empty_message_copy(_dst, _id); { @@ -507,14 +478,13 @@ namespace pEp { } PEP_STATUS MessageCache::encrypt_message_for_self( - PEP_SESSION session, - pEp_identity* target_id, - message *src, - stringlist_t* extra, - message **dst, - PEP_enc_format enc_format, - PEP_encrypt_flags_t flags - ) + PEP_SESSION session, + pEp_identity *target_id, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags) { ::message *_msg; std::string _id = cacheID(src); @@ -525,8 +495,14 @@ namespace pEp { } ::message *_dst = nullptr; - PEP_STATUS status = ::encrypt_message_for_self(session, target_id, src, - extra, &_dst, enc_format, flags); + PEP_STATUS status = ::encrypt_message_for_self( + session, + target_id, + src, + extra, + &_dst, + enc_format, + flags); *dst = empty_message_copy(_dst, _id); { @@ -538,5 +514,4 @@ namespace pEp { return status; } -}; - +}; // namespace pEp diff --git a/src/message_cache.hh b/src/message_cache.hh new file mode 100644 index 0000000..cd4aa2e --- /dev/null +++ b/src/message_cache.hh @@ -0,0 +1,128 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef LIBPEPADAPTER_MESSAGE_CACHE_HH +#define LIBPEPADAPTER_MESSAGE_CACHE_HH + +#include +#include +#include +#include +#include + +namespace pEp { + class MessageCache { + struct cache_entry { + cache_entry(::message *s, ::message *d) : src(s), dst(d) {} + + ::message *src; + ::message *dst; + }; + + using cache = std::unordered_map; + + cache _cache; + std::mutex _mtx; + long long id_range = 42; + long long next_id = 23; + + public: + MessageCache(); + + enum which + { + msg_src = 0, + msg_dst = 1 + }; + + static PEP_STATUS cache_mime_decode_message( + const char *mimetext, + size_t size, + message **msg, + bool *has_possible_pEp_msg); + + static PEP_STATUS cache_mime_encode_message( + int one, + const message *msg, + bool omit_fields, + char **mimetext, + bool has_pEp_msg_attachment); + + static PEP_STATUS cache_decrypt_message( + PEP_SESSION session, + message *src, + message **dst, + stringlist_t **keylist, + PEP_rating *rating, + PEP_decrypt_flags_t *flags); + + static PEP_STATUS cache_encrypt_message( + PEP_SESSION session, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags); + + static PEP_STATUS cache_encrypt_message_for_self( + PEP_SESSION session, + pEp_identity *target_id, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags); + + + static PEP_STATUS cache_release(std::string id); + static void removeCacheID(::message *msg); + + protected: + void release(std::string id); + + PEP_STATUS mime_decode_message( + const char *mimetext, + size_t size, + message **msg, + bool *has_possible_pEp_msg); + + PEP_STATUS mime_encode_message( + which one, + const message *src, + bool omit_fields, + char **mimetext, + bool has_pEp_msg_attachment); + + PEP_STATUS decrypt_message( + PEP_SESSION session, + message *src, + message **dst, + stringlist_t **keylist, + PEP_rating *rating, + PEP_decrypt_flags_t *flags); + + PEP_STATUS encrypt_message( + PEP_SESSION session, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags); + + PEP_STATUS encrypt_message_for_self( + PEP_SESSION session, + pEp_identity *target_id, + message *src, + stringlist_t *extra, + message **dst, + PEP_enc_format enc_format, + PEP_encrypt_flags_t flags); + + void generateCacheID(::message *msg); + static std::string cacheID(const ::message *msg); + }; + + extern MessageCache message_cache; +}; // namespace pEp + +#endif // LIBPEPADAPTER_MESSAGE_CACHE_HH diff --git a/src/pEpLog.cc b/src/pEpLog.cc new file mode 100644 index 0000000..753eb09 --- /dev/null +++ b/src/pEpLog.cc @@ -0,0 +1,43 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "pEpLog.hh" +#include +#include +#include +#include + + +namespace pEp { + namespace Adapter { + namespace pEpLog { + + std::mutex mtx; + + std::atomic_bool is_enabled{false}; + + void set_enabled(bool enabled) + { + is_enabled.store(enabled); + } + + bool get_enabled() + { + return is_enabled.load(); + } + + void log(std::string msg) + { + if (is_enabled.load()) { + std::lock_guard l(mtx); +#ifdef ANDROID + __android_log_print(ANDROID_LOG_DEBUG, "pEpDebugLog", "%s", msg.c_str()); +#else + std::cout << msg << std::endl; //std::endl also flushes +#endif + } + } + + } // namespace pEpLog + } // namespace Adapter +} // namespace pEp diff --git a/pEpLog.hh b/src/pEpLog.hh similarity index 51% rename from pEpLog.hh rename to src/pEpLog.hh index 16854bf..7229ecf 100644 --- a/pEpLog.hh +++ b/src/pEpLog.hh @@ -29,34 +29,36 @@ // use set_enabled_(bool) to turn logging on/off per backend #ifdef NDEBUG - #define pEpLog(msg) do{}while(0) + #define pEpLog(msg) \ + do { \ + } while (0) #else #ifdef ANDROID #include #endif - #define pEpLog(msg) \ - do { \ - std::stringstream msg_ss; \ - msg_ss << std::this_thread::get_id() << " - " << __FILE__ << "::" << __FUNCTION__ << " - " << msg; \ - pEp::Adapter::pEpLog::log(msg_ss.str()); \ - } while(0) + #define pEpLog(msg) \ + do { \ + std::stringstream msg_ss; \ + msg_ss << std::this_thread::get_id() << " - " << __FILE__ << "::" << __FUNCTION__ \ + << " - " << msg; \ + pEp::Adapter::pEpLog::log(msg_ss.str()); \ + } while (0) #endif // NDEBUG namespace pEp { -namespace Adapter { -namespace pEpLog { + namespace Adapter { + namespace pEpLog { -void log(std::string msg); + void log(std::string msg); -void set_enabled(bool is_enabled); + void set_enabled(bool is_enabled); -bool get_enabled(); + bool get_enabled(); -} // pEpLog -} // Adapter -} // pEp + } // namespace pEpLog + } // namespace Adapter +} // namespace pEp #endif // LIBPEPADAPTER_PEPLOG_HH - diff --git a/passphrase_cache.cc b/src/passphrase_cache.cc similarity index 79% rename from passphrase_cache.cc rename to src/passphrase_cache.cc index ee170f2..d3fe949 100644 --- a/passphrase_cache.cc +++ b/src/passphrase_cache.cc @@ -9,19 +9,19 @@ pEp::PassphraseCache pEp::passphrase_cache; namespace pEp { - PassphraseCache::cache_entry::cache_entry(const std::string& p, time_point t) : - passphrase{p, 0, PassphraseCache::cache_entry::max_len}, tp{t} - { } - - PassphraseCache::PassphraseCache(size_t max_size, duration timeout) : - _max_size{max_size}, _timeout{timeout}, _which(_cache.end()), - first_time(true) - { } - - PassphraseCache::PassphraseCache(const PassphraseCache& second) : - _cache{second._cache}, _max_size{second._max_size}, - _timeout{second._timeout}, _stored{second._stored}, - _which(_cache.end()), first_time(true) + PassphraseCache::cache_entry::cache_entry(const std::string& p, time_point t) + : passphrase{p, 0, PassphraseCache::cache_entry::max_len}, tp{t} + { + } + + PassphraseCache::PassphraseCache(size_t max_size, duration timeout) + : _max_size{max_size}, _timeout{timeout}, _which(_cache.end()), first_time(true) + { + } + + PassphraseCache::PassphraseCache(const PassphraseCache& second) + : _cache{second._cache}, _max_size{second._max_size}, _timeout{second._timeout}, + _stored{second._stored}, _which(_cache.end()), first_time(true) { cleanup(); } @@ -36,16 +36,16 @@ namespace pEp { return *this; } - const char *PassphraseCache::add(const std::string& passphrase) + const char* PassphraseCache::add(const std::string& passphrase) { if (!passphrase.empty()) { - const char *result = nullptr; + const char* result = nullptr; { std::lock_guard lock(_mtx); while (_cache.size() >= _max_size) _cache.pop_front(); - + _cache.push_back({passphrase, clock::now()}); auto back = _cache.end(); assert(!_cache.empty()); @@ -55,11 +55,11 @@ namespace pEp { return result; } - static const char *empty = ""; + static const char* empty = ""; return empty; } - const char *PassphraseCache::add_stored(const std::string& passphrase) + const char* PassphraseCache::add_stored(const std::string& passphrase) { std::lock_guard lock(_stored_mtx); _stored = passphrase; @@ -81,7 +81,7 @@ namespace pEp { std::lock_guard lock(_mtx); cleanup(); - for (auto entry=_cache.begin(); entry!=_cache.end(); ++entry) { + for (auto entry = _cache.begin(); entry != _cache.end(); ++entry) { if (callee(entry->passphrase)) { refresh(entry); return true; @@ -104,7 +104,7 @@ namespace pEp { _cache.splice(_cache.end(), _cache, entry); } - const char *PassphraseCache::latest_passphrase(PassphraseCache& c) + const char* PassphraseCache::latest_passphrase(PassphraseCache& c) { if (c.first_time) { c.cleanup(); @@ -128,8 +128,8 @@ namespace pEp { return c._which->passphrase.c_str(); } - PEP_STATUS PassphraseCache::config_next_passphrase(bool reset, PEP_SESSION session) - { + PEP_STATUS PassphraseCache::config_next_passphrase(bool reset, PEP_SESSION session) + { static pEp::PassphraseCache _copy; static bool new_copy = true; @@ -146,16 +146,14 @@ namespace pEp { try { ::config_passphrase(session ? session : Adapter::session(), latest_passphrase(_copy)); return PEP_STATUS_OK; - } - catch (pEp::PassphraseCache::Empty&) { + } catch (pEp::PassphraseCache::Empty&) { new_copy = true; return PEP_PASSPHRASE_REQUIRED; - } - catch (pEp::PassphraseCache::Exhausted&) { + } catch (pEp::PassphraseCache::Exhausted&) { new_copy = true; return PEP_WRONG_PASSPHRASE; } - } + } PEP_STATUS PassphraseCache::ensure_passphrase(PEP_SESSION session, std::string fpr) { @@ -172,5 +170,4 @@ namespace pEp { return status; } -}; - +}; // namespace pEp diff --git a/passphrase_cache.hh b/src/passphrase_cache.hh similarity index 80% rename from passphrase_cache.hh rename to src/passphrase_cache.hh index b514492..c16f13f 100644 --- a/passphrase_cache.hh +++ b/src/passphrase_cache.hh @@ -20,7 +20,7 @@ namespace pEp { struct cache_entry { static const size_t max_len = 250 * 4; - cache_entry(const std::string& p, time_point t); + cache_entry(const std::string& p, time_point t); std::string passphrase; time_point tp; @@ -39,30 +39,30 @@ namespace pEp { public: struct Empty : public std::underflow_error { - Empty() : std::underflow_error("passphrase cache empty") { } + Empty() : std::underflow_error("passphrase cache empty") {} }; struct Exhausted : public std::underflow_error { - Exhausted() : std::underflow_error("out of passphrases") { } + Exhausted() : std::underflow_error("out of passphrases") {} }; - PassphraseCache(size_t max_size=20, duration timeout = std::chrono::minutes(10)); - ~PassphraseCache() { } + PassphraseCache(size_t max_size = 20, duration timeout = std::chrono::minutes(10)); + ~PassphraseCache() {} PassphraseCache(const PassphraseCache& second); PassphraseCache& operator=(const PassphraseCache& second); // adds the passphrase to the cache, which will timeout // returns a ptr to the passsword entry in the cache. Don't free() it! - const char *add(const std::string& passphrase); + const char* add(const std::string& passphrase); // adds the stored passphrase to the cache, which will not timeout - const char *add_stored(const std::string& passphrase); + const char* add_stored(const std::string& passphrase); // call this function inside the messageToSend() implementation of the adapter // this function is using latest_passphrase() to test one passphrase after the // other until the cache is exhausted // call with reset = true to reset the iterator - static PEP_STATUS config_next_passphrase(bool reset=false, PEP_SESSION session = NULL); + static PEP_STATUS config_next_passphrase(bool reset = false, PEP_SESSION session = NULL); // convenience functions // i.e. @@ -71,10 +71,10 @@ namespace pEp { // status = ::encrypt_message(session, src, extra, dst, enc_format, flags) // using for_each_passphrase() - template PEP_STATUS api(PEP_STATUS f(PEP_SESSION, A...), - PEP_SESSION session, A... a); + template + PEP_STATUS api(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a); - static const char *latest_passphrase(PassphraseCache& _cache); + static const char* latest_passphrase(PassphraseCache& _cache); using passphrase_callee = std::function; bool for_each_passphrase(const passphrase_callee& callee); PEP_STATUS ensure_passphrase(PEP_SESSION session, std::string fpr); @@ -85,7 +85,7 @@ namespace pEp { }; extern PassphraseCache passphrase_cache; -}; +}; // namespace pEp #include "passphrase_cache.hxx" diff --git a/passphrase_cache.hxx b/src/passphrase_cache.hxx similarity index 69% rename from passphrase_cache.hxx rename to src/passphrase_cache.hxx index ad5c616..3bdce8d 100644 --- a/passphrase_cache.hxx +++ b/src/passphrase_cache.hxx @@ -7,8 +7,8 @@ #include "passphrase_cache.hh" namespace pEp { - template PEP_STATUS PassphraseCache::api( - PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a) + template + PEP_STATUS PassphraseCache::api(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a) { PEP_STATUS status; @@ -18,12 +18,11 @@ namespace pEp { return true; status = f(session, a...); - return status != PEP_PASSPHRASE_REQUIRED && - status != PEP_WRONG_PASSPHRASE; + return status != PEP_PASSPHRASE_REQUIRED && status != PEP_WRONG_PASSPHRASE; }); return status; } -}; +}; // namespace pEp #endif // LIBPEPADAPTER_PASSPHRASE_CACHE_HXX diff --git a/pc_container.hh b/src/pc_container.hh similarity index 100% rename from pc_container.hh rename to src/pc_container.hh diff --git a/src/slurp.cc b/src/slurp.cc new file mode 100644 index 0000000..a1f4436 --- /dev/null +++ b/src/slurp.cc @@ -0,0 +1,21 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "slurp.hh" +#include +#include +#include + +namespace pEp { + std::string slurp(const std::string& filename) + { + std::ifstream input(filename.c_str(), std::ios_base::binary); + if (!input) { + throw std::runtime_error("Cannot read file \"" + filename + "\"! "); + } + + std::stringstream sstr; + sstr << input.rdbuf(); + return sstr.str(); + } +} // end of namespace pEp diff --git a/slurp.hh b/src/slurp.hh similarity index 88% rename from slurp.hh rename to src/slurp.hh index 7e65eaf..66d45c2 100644 --- a/slurp.hh +++ b/src/slurp.hh @@ -6,8 +6,7 @@ #include -namespace pEp -{ +namespace pEp { // reads a whole file and returns it as std::string // throws std::runtime_error() if the file cannot be read. Empty file is not an error. std::string slurp(const std::string& filename); diff --git a/src/status_to_string.cc b/src/status_to_string.cc new file mode 100644 index 0000000..9a850a0 --- /dev/null +++ b/src/status_to_string.cc @@ -0,0 +1,23 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "status_to_string.hh" +#include + + +namespace pEp { + + // in pEpEngine.h positive values are hex, negative are decimal. :-o + // TODO: the code should be generated! + std::string status_to_string(PEP_STATUS status) + { + std::stringstream ss; + if (status > 0) { + ss << "0x" << std::hex << status; + } else { + ss << status; + } + return ss.str() + " \"" + pEp_status_to_string(status) + '"'; + } + +} // end of namespace pEp diff --git a/status_to_string.hh b/src/status_to_string.hh similarity index 96% rename from status_to_string.hh rename to src/status_to_string.hh index 5078ef3..9540fa6 100644 --- a/status_to_string.hh +++ b/src/status_to_string.hh @@ -8,12 +8,11 @@ #include #include -namespace pEp -{ +namespace pEp { // creates a textual string (returned by pep_status_to_string() ) and the numerical status value. // in pEpEngine.h positive values are in hex value, negatives in decimal. So we follow this. std::string status_to_string(PEP_STATUS status); - + } // end of namespace pEp #endif // LIBPEPADAPTER_STATUS_TO_STRING_HH diff --git a/status_to_string.cc b/status_to_string.cc deleted file mode 100644 index c95e36e..0000000 --- a/status_to_string.cc +++ /dev/null @@ -1,25 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#include "status_to_string.hh" -#include - - -namespace pEp -{ - -// in pEpEngine.h positive values are hex, negative are decimal. :-o -// TODO: the code should be generated! -std::string status_to_string(PEP_STATUS status) -{ - std::stringstream ss; - if(status>0) - { - ss << "0x" << std::hex << status; - }else{ - ss << status; - } - return ss.str() + " \"" + pEp_status_to_string(status) + '"'; -} - -} // end of namespace pEp diff --git a/test/Makefile b/test/Makefile index cdd2435..68a4624 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,8 +1,8 @@ include ../Makefile.conf -LDFLAGS=-L../ $(ENGINE_LIB) +LDFLAGS=-L../src $(ENGINE_LIB) LDLIBS=-lstdc++ -lpEpEngine -lpEpAdapter -CXXFLAGS+=-I../ $(ENGINE_INC) -std=c++11 -DENGINE_TEST=$(ENGINE_TEST) +CXXFLAGS+=-I../src $(ENGINE_INC) -std=c++11 -DENGINE_TEST=$(ENGINE_TEST) SRC=$(wildcard test_*.cc) TST=$(subst .cc,,$(SRC)) @@ -13,7 +13,7 @@ $(TST): framework.o .PHONY: clean rmtestdata -clean: +clean: rm -f $(TST) rm -Rf *.dSYM rm -f *.o