From c6d8db4933f2ea588b381ebb8ba80c7d085d11ab Mon Sep 17 00:00:00 2001 From: Volker Birk Date: Wed, 29 Aug 2018 17:12:39 +0200 Subject: [PATCH] =?UTF-8?q?changes,=20lots=20of=20changes=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.py | 8 +- src/adapter.cc | 96 ++++++++++++++++++++++ src/adapter.hh | 62 ++++++++++++++ src/basic_api.cc | 12 +-- src/identity.cc | 6 +- src/message.cc | 10 +-- src/message.hh | 5 +- src/message_api.cc | 13 +-- src/pEpmodule.cc | 59 +++----------- src/pEpmodule.hh | 3 +- src/sync_mixin.cc | 186 ------------------------------------------ src/sync_mixin.hh | 86 ------------------- src/user_interface.cc | 66 +++++++++++++++ src/user_interface.hh | 48 +++++++++++ 14 files changed, 313 insertions(+), 347 deletions(-) create mode 100644 src/adapter.cc create mode 100644 src/adapter.hh delete mode 100644 src/sync_mixin.cc delete mode 100644 src/sync_mixin.hh create mode 100644 src/user_interface.cc create mode 100644 src/user_interface.hh diff --git a/setup.py b/setup.py index 609f524..98eb758 100644 --- a/setup.py +++ b/setup.py @@ -54,10 +54,10 @@ module_pEp = Extension('pEp', sources = glob('src/*.cc'), libraries = ['pEpEngine', 'boost_python3-mt', 'boost_locale-mt',], extra_compile_args = compile_args, - include_dirs = set( [ find(file, includes) for file in - search_for_includes ] ), - library_dirs = set( [ find(file, libraries) for file in - search_for_libraries ] ), + include_dirs = list(set( [ find(file, includes) for file in + search_for_includes ] )), + library_dirs = list(set( [ find(file, libraries) for file in + search_for_libraries ] )), ) diff --git a/src/adapter.cc b/src/adapter.cc new file mode 100644 index 0000000..03b7142 --- /dev/null +++ b/src/adapter.cc @@ -0,0 +1,96 @@ +// This file is under GNU Affero General Public License 3.0 +// see LICENSE.txt + +#include "user_interface.hh" +#include + +namespace pEp { + namespace PythonAdapter { + Adapter::Adapter() + { + session(init); + } + + Adapter::~Adapter() + { + session(release); + } + + PEP_SESSION Adapter::session(session_action action) + { + lock_guard lock(mtx); + + thread_local static PEP_SESSION _session = nullptr; + thread_local int booked = 0; + PEP_STATUS status = PEP_STATUS_OK; + + switch (action) { + case release: + if (booked) + --booked; + if (!booked && _session) { + ::release(_session); + _session = nullptr; + } + break; + + case none: + if (_session) + break; + + case init: + ++booked; + if (!_session) + status = ::init(&_session, _messageToSend, _inject_sync_event); + break; + + default: + status = PEP_ILLEGAL_VALUE; + } + + if (status) + _throw_status(status); + + return _session; + } + + PyObject *Adapter::ui_object(PyObject *value) + { + lock_guard lock(mtx); + static PyObject *obj = nullptr; + if (value) + obj = value; + return obj; + } + + PEP_STATUS Adapter::_messageToSend(struct _message *msg) + { + if (!msg) + return PEP_ILLEGAL_VALUE; + + adapter.messageToSend(Message(msg)); + return PEP_STATUS_OK; + } + + int Adapter::_inject_sync_event(SYNC_EVENT ev, void *management) + { + if (is_sync_thread(adapter.session())) { + PEP_STATUS status = do_sync_protocol_step(adapter.session(), adapter.ui_object(), ev); + return status == PEP_STATUS_OK ? 0 : 1; + } + + try { + q.push_front(ev); + } + catch (exception&) { + return 1; + } + return 0; + } + + void Adapter_callback::messageToSend(Message msg) { + call_method< void >(_self, "messageToSend", msg); + } + } +} + diff --git a/src/adapter.hh b/src/adapter.hh new file mode 100644 index 0000000..4abedd7 --- /dev/null +++ b/src/adapter.hh @@ -0,0 +1,62 @@ +// This file is under GNU Affero General Public License 3.0 +// see LICENSE.txt + +#pragma once + +#include "pEpmodule.hh" +#include "locked_queue.hh" +#include "user_interface.hh" +#include + +namespace pEp { + namespace PythonAdapter { + using Message = pEp::PythonAdapter::Message; + + class Adapter { + public: + Adapter(); + virtual ~Adapter(); + + virtual void messageToSend(Message msg) { + throw runtime_error("override this method"); + } + + enum session_action { + none = 0, + init, + release + }; + + PEP_SESSION session(session_action action = none); + static ::utility::locked_queue< SYNC_EVENT > q; + + protected: + static PyObject *ui_object(PyObject *value = nullptr); + static PEP_STATUS _messageToSend(struct _message *msg); + static int _inject_sync_event(SYNC_EVENT ev, void *management); + + private: + static mutex mtx; + + // non copyable + Adapter(const Adapter&) = delete; + Adapter& operator= (const Adapter&) = delete; + + friend class UserInterface_callback; + }; + + class Adapter_callback : public Adapter { + PyObject *_self; + public: + Adapter_callback(PyObject *self) : _self(self) { } + ~Adapter_callback() { } + + void messageToSend(Message msg); + + // non copyable + Adapter_callback(const Adapter_callback&) = delete; + Adapter_callback& operator= (const Adapter_callback&) = delete; + }; + } +} + diff --git a/src/basic_api.cc b/src/basic_api.cc index 27341e3..f41bbcc 100644 --- a/src/basic_api.cc +++ b/src/basic_api.cc @@ -16,7 +16,7 @@ namespace pEp { throw runtime_error("update_identity: '" PEP_OWN_USERID "' may only be used for own identities"); - PEP_STATUS status = update_identity(session, ident); + PEP_STATUS status = update_identity(adapter.session(), ident); _throw_status(status); } @@ -31,7 +31,7 @@ namespace pEp { ident.user_id(PEP_OWN_USERID); - PEP_STATUS status = myself(session, ident); + PEP_STATUS status = myself(adapter.session(), ident); _throw_status(status); } @@ -45,7 +45,7 @@ namespace pEp { char *words = NULL; size_t size = 0; - PEP_STATUS status = get_trustwords(session, me, partner, + PEP_STATUS status = get_trustwords(adapter.session(), me, partner, lang.c_str(),&words, &size, full); _throw_status(status); return words; @@ -58,7 +58,7 @@ namespace pEp { if (ident.user_id() == "") throw invalid_argument("user_id must be provided"); - PEP_STATUS status = trust_personal_key(session, ident); + PEP_STATUS status = trust_personal_key(adapter.session(), ident); _throw_status(status); } @@ -69,7 +69,7 @@ namespace pEp { if (ident.user_id() == "") throw invalid_argument("user_id needed"); - PEP_STATUS status = set_identity_flags(session, ident, flags); + PEP_STATUS status = set_identity_flags(adapter.session(), ident, flags); _throw_status(status); } @@ -80,7 +80,7 @@ namespace pEp { if (ident.user_id() == "") throw invalid_argument("user_id needed"); - PEP_STATUS status = unset_identity_flags(session, ident, flags); + PEP_STATUS status = unset_identity_flags(adapter.session(), ident, flags); _throw_status(status); } } diff --git a/src/identity.cc b/src/identity.cc index 691645d..09e89fd 100644 --- a/src/identity.cc +++ b/src/identity.cc @@ -118,7 +118,7 @@ namespace pEp { throw invalid_argument("address must be given"); PEP_rating rating = PEP_rating_undefined; - PEP_STATUS status = ::identity_rating(session, _ident.get(), &rating); + PEP_STATUS status = ::identity_rating(adapter.session(), _ident.get(), &rating); _throw_status(status); return (int) rating; @@ -187,7 +187,7 @@ namespace pEp { pEp_identity *_dup = ::identity_dup(_ident); if (!_dup) throw bad_alloc(); - PEP_STATUS status = update_identity(session, _dup); + PEP_STATUS status = update_identity(adapter.session(), _dup); _throw_status(status); free_identity(ident); ident = _dup; @@ -225,7 +225,7 @@ namespace pEp { free_identity_list(_il); throw bad_alloc(); } - PEP_STATUS status = update_identity(session, _dup); + PEP_STATUS status = update_identity(adapter.session(), _dup); if (status != PEP_STATUS_OK) { free_identity_list(_il); _throw_status(status); diff --git a/src/message.cc b/src/message.cc index 81999bf..a6e79cc 100644 --- a/src/message.cc +++ b/src/message.cc @@ -313,15 +313,15 @@ namespace pEp { if (!(_msg && _msg->from)) throw invalid_argument("from must be a valid Identity()"); if (_msg->dir == PEP_dir_outgoing) - myself(session, _msg->from); + myself(adapter.session(), _msg->from); else - update_identity(session, _msg->from); + update_identity(adapter.session(), _msg->from); if (!(_msg->dir == PEP_dir_outgoing && _msg->from->user_id && strcmp(_msg->from->user_id, PEP_OWN_USERID) == 0)) throw invalid_argument("Message.dir must be outgoing"); PEP_rating rating = PEP_rating_undefined; - PEP_STATUS status = outgoing_message_rating(session, *this, &rating); + PEP_STATUS status = outgoing_message_rating(adapter.session(), *this, &rating); _throw_status(status); return (int) rating; @@ -347,14 +347,14 @@ namespace pEp { Message outgoing_message(Identity me) { - ::myself(session, me); + ::myself(adapter.session(), me); auto m = Message(PEP_dir_outgoing, &me); return m; } static object update(Identity ident) { - update_identity(session, ident); + update_identity(adapter.session(), ident); return object(ident); } diff --git a/src/message.hh b/src/message.hh index b4cb038..79c75f2 100644 --- a/src/message.hh +++ b/src/message.hh @@ -7,11 +7,12 @@ #include #include #include -#include "pEpmodule.hh" +#include "str_attr.hh" +#include "identity.hh" namespace pEp { namespace PythonAdapter { - using namespace utility; + using namespace std; using namespace boost::python; using boost::lexical_cast; diff --git a/src/message_api.cc b/src/message_api.cc index 74e8c90..c88bd63 100644 --- a/src/message_api.cc +++ b/src/message_api.cc @@ -4,7 +4,8 @@ #include "message_api.hh" #include #include -#include +#include +#include namespace pEp { namespace PythonAdapter { @@ -23,7 +24,7 @@ namespace pEp { message *_dst = NULL; message *_src = src; - PEP_STATUS status = encrypt_message(session, _src, _extra, &_dst, + PEP_STATUS status = encrypt_message(adapter.session(), _src, _extra, &_dst, _enc_format, _flags); free_stringlist(_extra); _throw_status(status); @@ -42,7 +43,7 @@ namespace pEp { PEP_decrypt_flags_t _flags = 0; message *_src = src; - PEP_STATUS status = decrypt_message(session, _src, &_dst, &_keylist, + PEP_STATUS status = decrypt_message(adapter.session(), _src, &_dst, &_keylist, &_rating, &_flags); _throw_status(status); @@ -70,7 +71,7 @@ namespace pEp { void _config_keep_sync_msg(bool enabled) { - ::config_keep_sync_msg(session, enabled); + ::config_keep_sync_msg(adapter.session(), enabled); } boost::python::tuple sync_decode(object buffer) @@ -81,7 +82,7 @@ namespace pEp { throw invalid_argument("need a contiguous buffer to read"); char *dst = NULL; - PEP_STATUS status = decode_sync_msg((char *) src.buf, src.len, &dst); + PEP_STATUS status = PER_to_XER_Sync_msg((char *) src.buf, src.len, &dst); PyBuffer_Release(&src); _throw_status(status); @@ -94,7 +95,7 @@ namespace pEp { { char *data = NULL; size_t size = 0; - PEP_STATUS status = encode_sync_msg(text.c_str(), &data, &size); + PEP_STATUS status = XER_to_PER_Sync_msg(text.c_str(), &data, &size); _throw_status(status); PyObject *ba = PyBytes_FromStringAndSize(data, size); diff --git a/src/pEpmodule.cc b/src/pEpmodule.cc index c5551a9..2291d5a 100644 --- a/src/pEpmodule.cc +++ b/src/pEpmodule.cc @@ -8,7 +8,7 @@ #include #include "basic_api.hh" #include "message_api.hh" -#include "sync_mixin.hh" +#include "user_interface.hh" #include @@ -19,6 +19,8 @@ namespace pEp { namespace PythonAdapter { using namespace std; + Adapter adapter; + static const char *version_string = "p≡p Python adapter version 0.2"; static string about() { @@ -27,14 +29,9 @@ namespace pEp { return version; } - std::mutex init_mutex; - - PEP_SESSION session = NULL; - static void free_module(void *) { - std::lock_guard lock(init_mutex); - release(session); + } void _throw_status(PEP_STATUS status) @@ -365,9 +362,9 @@ BOOST_PYTHON_MODULE(pEp) .value("SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED" , SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED) .value("SYNC_NOTIFY_OVERTAKEN" , SYNC_NOTIFY_OVERTAKEN); - auto sync_mixin_class = class_( - "SyncMixIn", - "class MySyncHandler(SyncMixIn):\n" + auto sync_mixin_class = class_( + "UserInterface", + "class MySyncHandler(UserInterface):\n" " def messageToSend(self, msg):\n" " ...\n" "\n" @@ -383,51 +380,27 @@ BOOST_PYTHON_MODULE(pEp) "p≡p Sync MixIn\n" "\n" "write a handler class to enable p≡p sync protocol\n") - .def("messageToSend", &SyncMixIn::messageToSend, + .def("messageToSend", &Adapter::messageToSend, "messageToSend(self, msg)" "\n" " msg p≡p message to send\n" "\n" "overwrite this method with code actually sending msg") - .def("notifyHandshake", &SyncMixIn::notifyHandshake, + .def("notifyHandshake", &UserInterface::notifyHandshake, "notifyHandshake(self, me, partner)\n" "\n" " me own identity\n" " partner identity of communication partner\n" "\n" "overwrite this method with code showing a trustwords dialog") -#ifndef NDEBUG - .def("inject", &SyncMixIn::_inject, - "inject(self, event, partner, extra)\n" - "\n" - " event number of event to inject\n" - " partner identity of communication partner\n" - " extra optional extra data or None\n" - "\n" - "inject an event into the sync state machine (for debugging purposes only)") -#endif - .def("deliverHandshakeResult", &SyncMixIn::deliverHandshakeResult, + .def("deliverHandshakeResult", &UserInterface::deliverHandshakeResult, "deliverHandshakeResult(self, partber, result)\n" "\n" " partner identity of communication partner\n" " result -1: cancel, 0: accepted, 1: rejected\n" "\n" "call to deliver the handshake result") - .def("setTimeout", &SyncMixIn::setTimeout, - "setTimeout(self, timeout)\n" - "\n" - " timeout timeout to wait for\n" - "\n" - "overwrite this method with code setting timeout timer") - .def("cancelTimeout", &SyncMixIn::cancelTimeout, - "cancelTimeout(self)\n" - "\n" - "overwrite this method with code canceling timeout timer") - .def("onTimeout", &SyncMixIn::onTimeout, - "onTimeout(self)\n" - "\n" - "call this method when timeout occurs"); - + ; // codecs call< object >(((object)(import("codecs").attr("register"))).ptr(), make_function(sync_search)); @@ -436,14 +409,4 @@ BOOST_PYTHON_MODULE(pEp) PyModuleDef * _def = PyModule_GetDef(scope().ptr()); _def->m_free = free_module; - - std::lock_guard lock(init_mutex); - PEP_STATUS status = ::init(&session); - if (status != PEP_STATUS_OK) { - stringstream ss; - ss << "init session failed with error " << status; - string s; - ss >> s; - throw runtime_error(s); - } } diff --git a/src/pEpmodule.hh b/src/pEpmodule.hh index 3fc1030..37fc4f5 100644 --- a/src/pEpmodule.hh +++ b/src/pEpmodule.hh @@ -3,12 +3,13 @@ #include #include "identity.hh" #include "message.hh" +#include "adapter.hh" #include namespace pEp { namespace PythonAdapter { - extern PEP_SESSION session; void _throw_status(PEP_STATUS status); + extern Adapter adapter; } } diff --git a/src/sync_mixin.cc b/src/sync_mixin.cc deleted file mode 100644 index 8333609..0000000 --- a/src/sync_mixin.cc +++ /dev/null @@ -1,186 +0,0 @@ -// This file is under GNU Affero General Public License 3.0 -// see LICENSE.txt - -#include "sync_mixin.hh" -#ifndef NDEBUG -#include -#endif -#include - -namespace pEp { - namespace PythonAdapter { - SyncMixIn_callback::SyncMixIn_callback(PyObject *self) : _self(self) - { - PEP_STATUS status = register_sync_callbacks(session, (void *) this, - _messageToSend, _notifyHandshake, inject_sync_msg, - retrieve_next_sync_msg); - assert(status == PEP_STATUS_OK); - } - - SyncMixIn_callback::~SyncMixIn_callback() - { - unregister_sync_callbacks(session); - } - - PEP_STATUS SyncMixIn::_messageToSend(void *obj, message *msg) - { - if (!obj) - return PEP_SEND_FUNCTION_NOT_REGISTERED; - - if (!msg) - return PEP_ILLEGAL_VALUE; - - auto that = dynamic_cast< SyncMixIn_callback * >( - static_cast< SyncMixIn * > (obj)); - that->messageToSend(Message(msg)); - - return PEP_STATUS_OK; - } - - PEP_STATUS SyncMixIn::_notifyHandshake(void *obj, - pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal) - { - if (!obj) - return PEP_SEND_FUNCTION_NOT_REGISTERED; - - if (!(me && partner)) - return PEP_ILLEGAL_VALUE; - - auto that = dynamic_cast< SyncMixIn_callback * >( - static_cast< SyncMixIn * > (obj)); - that->notifyHandshake(Identity(me), Identity(partner), signal); - - return PEP_STATUS_OK; - } - - void SyncMixIn::deliverHandshakeResult(Identity partner, int result) - { - PEP_STATUS status = ::deliverHandshakeResult(session, partner, - (sync_handshake_result) result); - _throw_status(status); - } - -#ifndef NDEBUG - void SyncMixIn::_inject(int event, Identity partner, object extra) - { - time_t timeout = 0; - PEP_STATUS status = fsm_DeviceState_inject(session, - (DeviceState_event) event, partner, NULL, &timeout); - _throw_status(status); - } -#endif - - jmp_buf SyncMixIn::env; - void *SyncMixIn::_msg; - - timeout_state_t SyncMixIn::timeout_state = timeout_stopped; - bool SyncMixIn::last_turn = false; - time_t SyncMixIn::remaining_time = 0; - - int SyncMixIn::inject_sync_msg(void *msg, void *management) - { - assert(timeout_state != timeout_canceling); - if(timeout_state == timeout_canceling) return 0; - - assert(timeout_state != timeout_expiring); - if(timeout_state == timeout_expiring) return 0; - - _msg = msg; - int val = setjmp(env); - if (!val){ - if(timeout_state == timeout_running){ - // call python timeout timer cancel - auto that = dynamic_cast< SyncMixIn_callback * >( - static_cast< SyncMixIn * > (management)); - remaining_time = that->cancelTimeout(); - timeout_state = timeout_canceling; - } - last_turn = false; - do_sync_protocol(session, management); - } - return 0; - } - - void *SyncMixIn::retrieve_next_sync_msg(void *management, time_t *timeout) - { - if (!last_turn){ - - assert(timeout_state != timeout_running); - if(timeout_state == timeout_running) return NULL; - - switch(timeout_state){ - case timeout_canceling : - *timeout = remaining_time; - break; - case timeout_expiring : - // "1" is arbitrary value !=0, since we don't - // have original timeout value anymore - *timeout = 1; - break; - default: - ; - } - - timeout_state = timeout_stopped; - - last_turn = true; - return (void *) _msg; - - } else { - - assert(timeout_state == timeout_stopped); - if(timeout_state != timeout_stopped) return NULL; - - if (*timeout != 0) { - // call python timeout timer start - auto that = dynamic_cast< SyncMixIn_callback * >( - static_cast< SyncMixIn * > (management)); - that->setTimeout(*timeout); - timeout_state = timeout_running; - } - } - longjmp(env, 1); - return (void *) 23; - } - - // to be called from python timeout timer - may GIL protect us - void SyncMixIn::onTimeout(){ - assert(timeout_state != timeout_canceling); - if(timeout_state == timeout_canceling) return; - - assert(timeout_state != timeout_expiring); - if(timeout_state == timeout_expiring) return; - - _msg = NULL; - int val = setjmp(env); - if (!val){ - timeout_state = timeout_expiring; - - last_turn = false; - do_sync_protocol(session, (void*)this); - } - } - - void SyncMixIn_callback::messageToSend(Message msg) - { - call_method< void >(_self, "messageToSend", msg); - } - - void SyncMixIn_callback::notifyHandshake( - Identity me, Identity partner, sync_handshake_signal signal) - { - call_method< void >(_self, "notifyHandshake", me, partner, signal); - } - - void SyncMixIn_callback::setTimeout(time_t timeout) - { - call_method< void >(_self, "setTimeout", timeout); - } - - time_t SyncMixIn_callback::cancelTimeout() - { - return call_method< time_t >(_self, "cancelTimeout"); - } - } -} - diff --git a/src/sync_mixin.hh b/src/sync_mixin.hh deleted file mode 100644 index 65c0e0d..0000000 --- a/src/sync_mixin.hh +++ /dev/null @@ -1,86 +0,0 @@ -// This file is under GNU Affero General Public License 3.0 -// see LICENSE.txt - -#pragma once - -#include "pEpmodule.hh" -#include -#include - -namespace pEp { - namespace PythonAdapter { - - typedef enum _timeout_state_t { - timeout_stopped, - timeout_running, - timeout_canceling, - timeout_expiring - } timeout_state_t; - - class SyncMixIn { - public: - SyncMixIn() { } - virtual ~SyncMixIn() { } - - virtual void messageToSend(Message msg) { - throw runtime_error("override this method"); - } - - virtual void notifyHandshake( - pEp::PythonAdapter::Identity me, - pEp::PythonAdapter::Identity partner, - sync_handshake_signal signal) - { - throw runtime_error("override this method"); - } - - virtual void deliverHandshakeResult( - pEp::PythonAdapter::Identity partner, int result); -#ifndef NDEBUG - virtual void _inject( - int event, - pEp::PythonAdapter::Identity partner, object extra); -#endif - virtual void setTimeout(time_t timeout){ - throw runtime_error("override this method"); - } - - virtual time_t cancelTimeout(){ - throw runtime_error("override this method"); - } - - virtual void onTimeout(); - - protected: - static PEP_STATUS _messageToSend(void *obj, message *msg); - static PEP_STATUS _notifyHandshake(void *obj, - pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); - - static jmp_buf env; - static void *_msg; - static timeout_state_t timeout_state; - static bool last_turn; - static time_t remaining_time; - static int inject_sync_msg(void *msg, void *management); - static void *retrieve_next_sync_msg(void *management, time_t *timeout); - }; - - class SyncMixIn_callback : public SyncMixIn { - PyObject* const _self; - - public: - SyncMixIn_callback(PyObject *self); - ~SyncMixIn_callback(); - - void messageToSend(Message msg); - void notifyHandshake( - pEp::PythonAdapter::Identity me, - pEp::PythonAdapter::Identity partner, - sync_handshake_signal signal); - - void setTimeout(time_t timeout); - time_t cancelTimeout(); - }; - } -} - diff --git a/src/user_interface.cc b/src/user_interface.cc new file mode 100644 index 0000000..198dc78 --- /dev/null +++ b/src/user_interface.cc @@ -0,0 +1,66 @@ +// This file is under GNU Affero General Public License 3.0 +// see LICENSE.txt + +#include "user_interface.hh" +#include +#include + +namespace pEp { + namespace PythonAdapter { + UserInterface_callback::UserInterface_callback(PyObject *self) : + _self(self) + { + adapter.ui_object(self); + PEP_STATUS status = ::register_sync_callbacks(adapter.session(), + (void *) this, _notifyHandshake, retrieve_next_sync_event); + assert(status == PEP_STATUS_OK); + if (status) + _throw_status(status); + } + + UserInterface_callback::~UserInterface_callback() + { + ::unregister_sync_callbacks(adapter.session()); + } + + PEP_STATUS UserInterface::_notifyHandshake(void *obj, + pEp_identity *me, pEp_identity *partner, + sync_handshake_signal signal + ) + { + if (!obj) + return PEP_SEND_FUNCTION_NOT_REGISTERED; + + if (!(me && partner)) + return PEP_ILLEGAL_VALUE; + + auto that = dynamic_cast< UserInterface_callback * >( + static_cast< UserInterface * > (obj)); + that->notifyHandshake(Identity(me), Identity(partner), signal); + + return PEP_STATUS_OK; + } + + void UserInterface::deliverHandshakeResult(Identity partner, + int result) + { + PEP_STATUS status = ::deliverHandshakeResult(adapter.session(), + partner, (sync_handshake_result) result); + _throw_status(status); + } + + SYNC_EVENT UserInterface::retrieve_next_sync_event(void *management) + { + while (adapter.q.empty()) + nanosleep((const struct timespec[]){{0, 100000000L}}, NULL); + return adapter.q.pop_front(); + } + + void UserInterface_callback::notifyHandshake( + Identity me, Identity partner, sync_handshake_signal signal) + { + call_method< void >(_self, "notifyHandshake", me, partner, signal); + } + } +} + diff --git a/src/user_interface.hh b/src/user_interface.hh new file mode 100644 index 0000000..115bff8 --- /dev/null +++ b/src/user_interface.hh @@ -0,0 +1,48 @@ +// This file is under GNU Affero General Public License 3.0 +// see LICENSE.txt + +#pragma once + +#include "pEpmodule.hh" +#include +#include + +namespace pEp { + namespace PythonAdapter { + class UserInterface { + public: + UserInterface() { } + virtual ~UserInterface() { } + + virtual void notifyHandshake( + pEp::PythonAdapter::Identity me, + pEp::PythonAdapter::Identity partner, + sync_handshake_signal signal) + { + throw runtime_error("override this method"); + } + + virtual void deliverHandshakeResult( + pEp::PythonAdapter::Identity partner, int result); + + protected: + static PEP_STATUS _notifyHandshake(void *obj, pEp_identity *me, + pEp_identity *partner, sync_handshake_signal signal); + static SYNC_EVENT retrieve_next_sync_event( void *management); + }; + + class UserInterface_callback : public UserInterface { + PyObject *_self; + + public: + UserInterface_callback(PyObject *self); + ~UserInterface_callback(); + + void notifyHandshake( + pEp::PythonAdapter::Identity me, + pEp::PythonAdapter::Identity partner, + sync_handshake_signal signal); + }; + } +} +