Browse Source

changes, lots of changes…

PYADPT-55
Volker Birk 7 years ago
parent
commit
c6d8db4933
  1. 8
      setup.py
  2. 96
      src/adapter.cc
  3. 62
      src/adapter.hh
  4. 12
      src/basic_api.cc
  5. 6
      src/identity.cc
  6. 10
      src/message.cc
  7. 5
      src/message.hh
  8. 13
      src/message_api.cc
  9. 59
      src/pEpmodule.cc
  10. 3
      src/pEpmodule.hh
  11. 186
      src/sync_mixin.cc
  12. 86
      src/sync_mixin.hh
  13. 66
      src/user_interface.cc
  14. 48
      src/user_interface.hh

8
setup.py

@ -54,10 +54,10 @@ module_pEp = Extension('pEp',
sources = glob('src/*.cc'), sources = glob('src/*.cc'),
libraries = ['pEpEngine', 'boost_python3-mt', 'boost_locale-mt',], libraries = ['pEpEngine', 'boost_python3-mt', 'boost_locale-mt',],
extra_compile_args = compile_args, extra_compile_args = compile_args,
include_dirs = set( [ find(file, includes) for file in include_dirs = list(set( [ find(file, includes) for file in
search_for_includes ] ), search_for_includes ] )),
library_dirs = set( [ find(file, libraries) for file in library_dirs = list(set( [ find(file, libraries) for file in
search_for_libraries ] ), search_for_libraries ] )),
) )

96
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 <assert.h>
namespace pEp {
namespace PythonAdapter {
Adapter::Adapter()
{
session(init);
}
Adapter::~Adapter()
{
session(release);
}
PEP_SESSION Adapter::session(session_action action)
{
lock_guard<mutex> 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<mutex> 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);
}
}
}

62
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 <pEp/sync_api.h>
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;
};
}
}

12
src/basic_api.cc

@ -16,7 +16,7 @@ namespace pEp {
throw runtime_error("update_identity: '" PEP_OWN_USERID throw runtime_error("update_identity: '" PEP_OWN_USERID
"' may only be used for own identities"); "' 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); _throw_status(status);
} }
@ -31,7 +31,7 @@ namespace pEp {
ident.user_id(PEP_OWN_USERID); ident.user_id(PEP_OWN_USERID);
PEP_STATUS status = myself(session, ident); PEP_STATUS status = myself(adapter.session(), ident);
_throw_status(status); _throw_status(status);
} }
@ -45,7 +45,7 @@ namespace pEp {
char *words = NULL; char *words = NULL;
size_t size = 0; 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); lang.c_str(),&words, &size, full);
_throw_status(status); _throw_status(status);
return words; return words;
@ -58,7 +58,7 @@ namespace pEp {
if (ident.user_id() == "") if (ident.user_id() == "")
throw invalid_argument("user_id must be provided"); 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); _throw_status(status);
} }
@ -69,7 +69,7 @@ namespace pEp {
if (ident.user_id() == "") if (ident.user_id() == "")
throw invalid_argument("user_id needed"); 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); _throw_status(status);
} }
@ -80,7 +80,7 @@ namespace pEp {
if (ident.user_id() == "") if (ident.user_id() == "")
throw invalid_argument("user_id needed"); 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); _throw_status(status);
} }
} }

6
src/identity.cc

@ -118,7 +118,7 @@ namespace pEp {
throw invalid_argument("address must be given"); throw invalid_argument("address must be given");
PEP_rating rating = PEP_rating_undefined; 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); _throw_status(status);
return (int) rating; return (int) rating;
@ -187,7 +187,7 @@ namespace pEp {
pEp_identity *_dup = ::identity_dup(_ident); pEp_identity *_dup = ::identity_dup(_ident);
if (!_dup) if (!_dup)
throw bad_alloc(); throw bad_alloc();
PEP_STATUS status = update_identity(session, _dup); PEP_STATUS status = update_identity(adapter.session(), _dup);
_throw_status(status); _throw_status(status);
free_identity(ident); free_identity(ident);
ident = _dup; ident = _dup;
@ -225,7 +225,7 @@ namespace pEp {
free_identity_list(_il); free_identity_list(_il);
throw bad_alloc(); throw bad_alloc();
} }
PEP_STATUS status = update_identity(session, _dup); PEP_STATUS status = update_identity(adapter.session(), _dup);
if (status != PEP_STATUS_OK) { if (status != PEP_STATUS_OK) {
free_identity_list(_il); free_identity_list(_il);
_throw_status(status); _throw_status(status);

10
src/message.cc

@ -313,15 +313,15 @@ namespace pEp {
if (!(_msg && _msg->from)) if (!(_msg && _msg->from))
throw invalid_argument("from must be a valid Identity()"); throw invalid_argument("from must be a valid Identity()");
if (_msg->dir == PEP_dir_outgoing) if (_msg->dir == PEP_dir_outgoing)
myself(session, _msg->from); myself(adapter.session(), _msg->from);
else else
update_identity(session, _msg->from); update_identity(adapter.session(), _msg->from);
if (!(_msg->dir == PEP_dir_outgoing && _msg->from->user_id && if (!(_msg->dir == PEP_dir_outgoing && _msg->from->user_id &&
strcmp(_msg->from->user_id, PEP_OWN_USERID) == 0)) strcmp(_msg->from->user_id, PEP_OWN_USERID) == 0))
throw invalid_argument("Message.dir must be outgoing"); throw invalid_argument("Message.dir must be outgoing");
PEP_rating rating = PEP_rating_undefined; 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); _throw_status(status);
return (int) rating; return (int) rating;
@ -347,14 +347,14 @@ namespace pEp {
Message outgoing_message(Identity me) Message outgoing_message(Identity me)
{ {
::myself(session, me); ::myself(adapter.session(), me);
auto m = Message(PEP_dir_outgoing, &me); auto m = Message(PEP_dir_outgoing, &me);
return m; return m;
} }
static object update(Identity ident) static object update(Identity ident)
{ {
update_identity(session, ident); update_identity(adapter.session(), ident);
return object(ident); return object(ident);
} }

5
src/message.hh

@ -7,11 +7,12 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <pEp/message.h> #include <pEp/message.h>
#include <string> #include <string>
#include "pEpmodule.hh" #include "str_attr.hh"
#include "identity.hh"
namespace pEp { namespace pEp {
namespace PythonAdapter { namespace PythonAdapter {
using namespace utility; using namespace std;
using namespace boost::python; using namespace boost::python;
using boost::lexical_cast; using boost::lexical_cast;

13
src/message_api.cc

@ -4,7 +4,8 @@
#include "message_api.hh" #include "message_api.hh"
#include <pEp/pEpEngine.h> #include <pEp/pEpEngine.h>
#include <pEp/message_api.h> #include <pEp/message_api.h>
#include <pEp/sync.h> #include <pEp/sync_api.h>
#include <pEp/Sync_codec.h>
namespace pEp { namespace pEp {
namespace PythonAdapter { namespace PythonAdapter {
@ -23,7 +24,7 @@ namespace pEp {
message *_dst = NULL; message *_dst = NULL;
message *_src = src; 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); _enc_format, _flags);
free_stringlist(_extra); free_stringlist(_extra);
_throw_status(status); _throw_status(status);
@ -42,7 +43,7 @@ namespace pEp {
PEP_decrypt_flags_t _flags = 0; PEP_decrypt_flags_t _flags = 0;
message *_src = src; message *_src = src;
PEP_STATUS status = decrypt_message(session, _src, &_dst, &_keylist, PEP_STATUS status = decrypt_message(adapter.session(), _src, &_dst, &_keylist,
&_rating, &_flags); &_rating, &_flags);
_throw_status(status); _throw_status(status);
@ -70,7 +71,7 @@ namespace pEp {
void _config_keep_sync_msg(bool enabled) 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) boost::python::tuple sync_decode(object buffer)
@ -81,7 +82,7 @@ namespace pEp {
throw invalid_argument("need a contiguous buffer to read"); throw invalid_argument("need a contiguous buffer to read");
char *dst = NULL; 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); PyBuffer_Release(&src);
_throw_status(status); _throw_status(status);
@ -94,7 +95,7 @@ namespace pEp {
{ {
char *data = NULL; char *data = NULL;
size_t size = 0; 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); _throw_status(status);
PyObject *ba = PyBytes_FromStringAndSize(data, size); PyObject *ba = PyBytes_FromStringAndSize(data, size);

59
src/pEpmodule.cc

@ -8,7 +8,7 @@
#include <iomanip> #include <iomanip>
#include "basic_api.hh" #include "basic_api.hh"
#include "message_api.hh" #include "message_api.hh"
#include "sync_mixin.hh" #include "user_interface.hh"
#include <mutex> #include <mutex>
@ -19,6 +19,8 @@ namespace pEp {
namespace PythonAdapter { namespace PythonAdapter {
using namespace std; using namespace std;
Adapter adapter;
static const char *version_string = "p≡p Python adapter version 0.2"; static const char *version_string = "p≡p Python adapter version 0.2";
static string about() static string about()
{ {
@ -27,14 +29,9 @@ namespace pEp {
return version; return version;
} }
std::mutex init_mutex;
PEP_SESSION session = NULL;
static void free_module(void *) static void free_module(void *)
{ {
std::lock_guard<std::mutex> lock(init_mutex);
release(session);
} }
void _throw_status(PEP_STATUS status) 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_ACCEPTED_DEVICE_MOVED" , SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED)
.value("SYNC_NOTIFY_OVERTAKEN" , SYNC_NOTIFY_OVERTAKEN); .value("SYNC_NOTIFY_OVERTAKEN" , SYNC_NOTIFY_OVERTAKEN);
auto sync_mixin_class = class_<SyncMixIn, SyncMixIn_callback, boost::noncopyable>( auto sync_mixin_class = class_<UserInterface, UserInterface_callback, boost::noncopyable>(
"SyncMixIn", "UserInterface",
"class MySyncHandler(SyncMixIn):\n" "class MySyncHandler(UserInterface):\n"
" def messageToSend(self, msg):\n" " def messageToSend(self, msg):\n"
" ...\n" " ...\n"
"\n" "\n"
@ -383,51 +380,27 @@ BOOST_PYTHON_MODULE(pEp)
"p≡p Sync MixIn\n" "p≡p Sync MixIn\n"
"\n" "\n"
"write a handler class to enable p≡p sync protocol\n") "write a handler class to enable p≡p sync protocol\n")
.def("messageToSend", &SyncMixIn::messageToSend, .def("messageToSend", &Adapter::messageToSend,
"messageToSend(self, msg)" "messageToSend(self, msg)"
"\n" "\n"
" msg p≡p message to send\n" " msg p≡p message to send\n"
"\n" "\n"
"overwrite this method with code actually sending msg") "overwrite this method with code actually sending msg")
.def("notifyHandshake", &SyncMixIn::notifyHandshake, .def("notifyHandshake", &UserInterface::notifyHandshake,
"notifyHandshake(self, me, partner)\n" "notifyHandshake(self, me, partner)\n"
"\n" "\n"
" me own identity\n" " me own identity\n"
" partner identity of communication partner\n" " partner identity of communication partner\n"
"\n" "\n"
"overwrite this method with code showing a trustwords dialog") "overwrite this method with code showing a trustwords dialog")
#ifndef NDEBUG .def("deliverHandshakeResult", &UserInterface::deliverHandshakeResult,
.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,
"deliverHandshakeResult(self, partber, result)\n" "deliverHandshakeResult(self, partber, result)\n"
"\n" "\n"
" partner identity of communication partner\n" " partner identity of communication partner\n"
" result -1: cancel, 0: accepted, 1: rejected\n" " result -1: cancel, 0: accepted, 1: rejected\n"
"\n" "\n"
"call to deliver the handshake result") "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 // codecs
call< object >(((object)(import("codecs").attr("register"))).ptr(), make_function(sync_search)); 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()); PyModuleDef * _def = PyModule_GetDef(scope().ptr());
_def->m_free = free_module; _def->m_free = free_module;
std::lock_guard<std::mutex> 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);
}
} }

3
src/pEpmodule.hh

@ -3,12 +3,13 @@
#include <boost/python.hpp> #include <boost/python.hpp>
#include "identity.hh" #include "identity.hh"
#include "message.hh" #include "message.hh"
#include "adapter.hh"
#include <pEp/pEpEngine.h> #include <pEp/pEpEngine.h>
namespace pEp { namespace pEp {
namespace PythonAdapter { namespace PythonAdapter {
extern PEP_SESSION session;
void _throw_status(PEP_STATUS status); void _throw_status(PEP_STATUS status);
extern Adapter adapter;
} }
} }

186
src/sync_mixin.cc

@ -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 <pEp/KeySync_fsm.h>
#endif
#include <assert.h>
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");
}
}
}

86
src/sync_mixin.hh

@ -1,86 +0,0 @@
// This file is under GNU Affero General Public License 3.0
// see LICENSE.txt
#pragma once
#include "pEpmodule.hh"
#include <setjmp.h>
#include <pEp/sync_api.h>
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();
};
}
}

66
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 <assert.h>
#include <time.h>
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);
}
}
}

48
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 <setjmp.h>
#include <pEp/sync_api.h>
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);
};
}
}
Loading…
Cancel
Save