Browse Source

Merge branch 'LIB-13' - Define Coding Standards And Project Structure

Define and implement Coding Style using clang-format.
top level .clang-format, supported by nearly all Editors/IDE's and if not, one has to manually run clang-format. Its up to the dev. But everybody can use it, and its enables to use a shared definition of coding style.

I want to avoid the project to end up in an underspecified/inconsistent state after the code base has grown over the years.
So, NOW is the time to do it.

Flat project structure becomes unmanageable.
Create standard project layout, of at least
* src
* test

for now

ALSO: The max. C++ Standard to be used (pEp-wide) has now been raised to C++14 (!!!)
pull/8/head
heck 4 years ago
parent
commit
ca0d30c175
  1. 39
      .clang-format
  2. 41
      Makefile
  3. 3
      Makefile.conf
  4. 0
      README.md
  5. 26
      call_with_lock.hh
  6. 23
      constant_time_algo.cc
  7. 135
      message_cache.hh
  8. 40
      pEpLog.cc
  9. 25
      slurp.cc
  10. 57
      src/Adapter.cc
  11. 32
      src/Adapter.hh
  12. 39
      src/Adapter.hxx
  13. 37
      src/Makefile
  14. 8
      src/Semaphore.hh
  15. 3
      src/call_with_lock.cc
  16. 26
      src/call_with_lock.hh
  17. 24
      src/callback_dispatcher.cc
  18. 14
      src/callback_dispatcher.hh
  19. 21
      src/constant_time_algo.cc
  20. 5
      src/constant_time_algo.hh
  21. 27
      src/locked_queue.hh
  22. 167
      src/message_cache.cc
  23. 128
      src/message_cache.hh
  24. 43
      src/pEpLog.cc
  25. 26
      src/pEpLog.hh
  26. 47
      src/passphrase_cache.cc
  27. 22
      src/passphrase_cache.hh
  28. 9
      src/passphrase_cache.hxx
  29. 0
      src/pc_container.hh
  30. 21
      src/slurp.cc
  31. 3
      src/slurp.hh
  32. 23
      src/status_to_string.cc
  33. 3
      src/status_to_string.hh
  34. 25
      status_to_string.cc
  35. 4
      test/Makefile

39
.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

41
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

3
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)

0
readme.md → README.md

26
call_with_lock.hh

@ -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 <mutex>
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<class R, class... Args>
R call_with_lock( R(*fn)(Args...), Args... args)
{
std::lock_guard<std::mutex> L(call_with_lock_mutex);
return fn(args...);
}
}
#endif // LIBPEPADAPTER_CALL_WITH_LOCK_HH

23
constant_time_algo.cc

@ -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.size(); ++idx)
{
d |= ( static_cast<unsigned>(a[idx]) ^ static_cast<unsigned>(b[idx]) );
}
// if d is still 0, the strings are equal.
return d == 0;
}
} // end of namespace pEp

135
message_cache.hh

@ -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 <string>
#include <unordered_map>
#include <mutex>
#include <pEp/message_api.h>
#include <pEp/mime.h>
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<std::string, cache_entry>;
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

40
pEpLog.cc

@ -1,40 +0,0 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "pEpLog.hh"
#include <iostream>
#include <sstream>
#include <mutex>
#include <atomic>
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<std::mutex> 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

25
slurp.cc

@ -1,25 +0,0 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "slurp.hh"
#include <fstream>
#include <sstream>
#include <stdexcept>
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

57
Adapter.cc → 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);
throw RuntimeError(_status, status);
}
RuntimeError::RuntimeError(const std::string& _text, PEP_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_EVENT, ::free_Sync_event> 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<mutex> 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);
@ -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) {
@ -150,5 +151,5 @@ namespace pEp {
return true;
}
}
}
}
} // namespace Adapter
} // namespace pEp

32
Adapter.hh → src/Adapter.hh

@ -5,10 +5,10 @@
#define LIBPEPADAPTER_ADAPTER_HH
#include <functional>
#include <memory>
#include <stdexcept>
#include <string>
#include <thread>
#include <stdexcept>
#include <memory>
#include <pEp/sync_api.h>
@ -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<class T = void>
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<void(T *)> _startup = nullptr,
std::function<void(T *)> _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
#endif // LIBPEPADAPTER_ADAPTER_HH

39
Adapter.hxx → 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<class T>
void sync_thread(T *obj, function<void(T *)> _startup, function<void(T *)> _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<class T>
void startup(
messageToSend_t messageToSend,
notifyHandshake_t notifyHandshake,
T *obj,
function< void(T *) > _startup,
function< void(T *) > _shutdown)
function<void(T *)> _startup,
function<void(T *)> _shutdown)
{
pEpLog("called");
if (messageToSend) {
@ -104,7 +107,7 @@ namespace pEp {
}
}
}
}
}
} // namespace Adapter
} // namespace pEp
#endif //LIBPEPADAPTER_ADAPTER_HXX
#endif // LIBPEPADAPTER_ADAPTER_HXX

37
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)

8
Semaphore.hh → 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

3
call_with_lock.cc → src/call_with_lock.cc

@ -3,7 +3,6 @@
#include "call_with_lock.hh"
namespace pEp
{
namespace pEp {
std::mutex call_with_lock_mutex;
}

26
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 <mutex>
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<class R, class... Args>
R call_with_lock(R (*fn)(Args...), Args... args)
{
std::lock_guard<std::mutex> L(call_with_lock_mutex);
return fn(args...);
}
} // namespace pEp
#endif // LIBPEPADAPTER_CALL_WITH_LOCK_HH

24
callback_dispatcher.cc → src/callback_dispatcher.cc

@ -14,8 +14,10 @@ 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);
}
@ -24,8 +26,7 @@ namespace pEp {
::messageToSend_t messageToSend,
::notifyHandshake_t notifyHandshake,
proc on_startup,
proc shutdown
)
proc shutdown)
{
assert(messageToSend);
if (!messageToSend) {
@ -77,8 +78,10 @@ namespace pEp {
pEpLog("called");
callback_dispatcher.semaphore.go();
pEp::Adapter::startup<CallbackDispatcher>(CallbackDispatcher::messageToSend,
CallbackDispatcher::notifyHandshake, &callback_dispatcher,
pEp::Adapter::startup<CallbackDispatcher>(
CallbackDispatcher::messageToSend,
CallbackDispatcher::notifyHandshake,
&callback_dispatcher,
&CallbackDispatcher::on_startup,
&CallbackDispatcher::on_shutdown);
@ -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

14
callback_dispatcher.hh → 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

21
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<unsigned>(a[idx]) ^ static_cast<unsigned>(b[idx]));
}
// if d is still 0, the strings are equal.
return d == 0;
}
} // end of namespace pEp

5
constant_time_algo.hh → src/constant_time_algo.hh

@ -6,14 +6,13 @@
#include <string>
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

27
locked_queue.hh → src/locked_queue.hh

@ -8,11 +8,9 @@
#include <condition_variable>
#include <mutex>
namespace utility
{
template<class T, void(*Deleter)(T) = nullptr>
class locked_queue
{
namespace utility {
template<class T, void (*Deleter)(T) = nullptr>
class locked_queue {
typedef std::recursive_mutex Mutex;
typedef std::unique_lock<Mutex> Lock;
@ -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,8 +82,7 @@ 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;
}
@ -104,8 +99,7 @@ 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;
}
@ -122,8 +116,7 @@ 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;
}

167
message_cache.cc → src/message_cache.cc

@ -25,35 +25,29 @@ namespace pEp {
message **dst,
stringlist_t **keylist,
PEP_rating *rating,
PEP_decrypt_flags_t *flags
)
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,
const message *msg,
bool omit_fields,
char **mimetext,
bool has_pEp_msg_attachment
)
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
)
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(
@ -62,25 +56,22 @@ namespace pEp {
stringlist_t *extra,
message **dst,
PEP_enc_format enc_format,
PEP_encrypt_flags_t flags
)
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,
pEp_identity *target_id,
message *src,
stringlist_t* extra,
stringlist_t *extra,
message **dst,
PEP_enc_format enc_format,
PEP_encrypt_flags_t flags
)
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();
@ -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,7 +252,7 @@ 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
@ -274,8 +264,7 @@ namespace pEp {
// 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;
@ -306,8 +295,7 @@ namespace pEp {
message **dst,
stringlist_t **keylist,
PEP_rating *rating,
PEP_decrypt_flags_t *flags
)
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);
{
@ -339,11 +326,10 @@ namespace pEp {
PEP_STATUS MessageCache::mime_encode_message(
which one,
const message * msg,
const message *msg,
bool omit_fields,
char **mimetext,
bool has_pEp_msg_attachment
)
bool has_pEp_msg_attachment)
{
if (!msg || cacheID(msg) == "")
return PEP_ILLEGAL_VALUE;
@ -357,16 +343,14 @@ namespace pEp {
std::lock_guard<std::mutex> l(_mtx);
::message *_src = _cache.at(cacheID(msg)).src;
swapContent(_msg, _src);
}
else /* msg_dst */ {
} else /* msg_dst */ {
std::lock_guard<std::mutex> 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;
@ -419,26 +399,21 @@ 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);
@ -454,21 +429,19 @@ namespace pEp {
const char *mimetext,
size_t size,
message **msg,
bool* has_possible_pEp_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<std::mutex> 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;
@ -480,8 +453,7 @@ namespace pEp {
stringlist_t *extra,
message **dst,
PEP_enc_format enc_format,
PEP_encrypt_flags_t flags
)
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);
{
@ -508,13 +479,12 @@ namespace pEp {
PEP_STATUS MessageCache::encrypt_message_for_self(
PEP_SESSION session,
pEp_identity* target_id,
pEp_identity *target_id,
message *src,
stringlist_t* extra,
stringlist_t *extra,
message **dst,
PEP_enc_format enc_format,
PEP_encrypt_flags_t flags
)
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

128
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 <string>
#include <unordered_map>
#include <mutex>
#include <pEp/message_api.h>
#include <pEp/mime.h>
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<std::string, cache_entry>;
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

43
src/pEpLog.cc

@ -0,0 +1,43 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "pEpLog.hh"
#include <iostream>
#include <sstream>
#include <mutex>
#include <atomic>
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<std::mutex> 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

26
pEpLog.hh → src/pEpLog.hh

@ -29,7 +29,9 @@
// use set_enabled_<backend>(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 <android/log.h>
@ -38,25 +40,25 @@
#define pEpLog(msg) \
do { \
std::stringstream msg_ss; \
msg_ss << std::this_thread::get_id() << " - " << __FILE__ << "::" << __FUNCTION__ << " - " << msg; \
msg_ss << std::this_thread::get_id() << " - " << __FILE__ << "::" << __FUNCTION__ \
<< " - " << msg; \
pEp::Adapter::pEpLog::log(msg_ss.str()); \
} while(0)
} 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

47
passphrase_cache.cc → 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,10 +36,10 @@ 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<std::mutex> lock(_mtx);
@ -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<std::mutex> lock(_stored_mtx);
_stored = passphrase;
@ -81,7 +81,7 @@ namespace pEp {
std::lock_guard<std::mutex> 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();
@ -146,12 +146,10 @@ 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;
}
@ -172,5 +170,4 @@ namespace pEp {
return status;
}
};
}; // namespace pEp

22
passphrase_cache.hh → src/passphrase_cache.hh

@ -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<typename... A> PEP_STATUS api(PEP_STATUS f(PEP_SESSION, A...),
PEP_SESSION session, A... a);
template<typename... A>
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(std::string)>;
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"

9
passphrase_cache.hxx → src/passphrase_cache.hxx

@ -7,8 +7,8 @@
#include "passphrase_cache.hh"
namespace pEp {
template<typename... A> PEP_STATUS PassphraseCache::api(
PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a)
template<typename... A>
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

0
pc_container.hh → src/pc_container.hh

21
src/slurp.cc

@ -0,0 +1,21 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "slurp.hh"
#include <fstream>
#include <sstream>
#include <stdexcept>
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

3
slurp.hh → src/slurp.hh

@ -6,8 +6,7 @@
#include <string>
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);

23
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 <sstream>
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

3
status_to_string.hh → src/status_to_string.hh

@ -8,8 +8,7 @@
#include <pEp/status_to_string.h>
#include <string>
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);

25
status_to_string.cc

@ -1,25 +0,0 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "status_to_string.hh"
#include <sstream>
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

4
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))

Loading…
Cancel
Save