CpEpEngine.h
author Markus Schaber <markus@pep-security.net>
Sat, 11 Feb 2017 17:49:02 +0100
changeset 234 a3cc1847d197
parent 233 27848ed0067c
child 235 581e3f7a92f5
permissions -rw-r--r--
COM-50: Handshake Requests need to be decoupled.

First implementation, trying to decouple purely via the COM server. If this
does not work out (e. G. reentrancy problems in Outlook), we need to pass the
callback down to outlook, and open a pseudo-modal dialog there (which blocks
the main window, but does not block the code like ShowDialog()).
     1 // CpEpEngine.h : Declaration of the CpEpEngine
     2 
     3 #pragma once
     4 #include "resource.h"       // main symbols
     5 
     6 #include "pEpComServerAdapter_i.h"
     7 #include "locked_queue.hh"
     8 #include "utf8_helper.h"
     9 #include "pEp_utility.h"
    10 #include <queue>
    11 
    12 #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
    13 #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
    14 #endif
    15 
    16 using namespace ATL;
    17 using namespace utility;
    18 using namespace pEp::utility;
    19 
    20 
    21 // CpEpEngine
    22 
    23 class ATL_NO_VTABLE CpEpEngine :
    24     public CComObjectRootEx<CComObjectThreadModel>,
    25 	public CComCoClass<CpEpEngine, &CLSID_pEpEngine>,
    26 	public ISupportErrorInfo,
    27 	public IpEpEngine2
    28 {
    29 protected:
    30     static int examine_identity(pEp_identity *ident, void *management);
    31 
    32 public:
    33     CpEpEngine() : keymanagement_thread(NULL), identity_queue(NULL), verbose_mode(false)
    34 	{
    35         PEP_STATUS status = ::init(&m_session);
    36         assert(status == PEP_STATUS_OK);
    37         ::register_examine_function(m_session, CpEpEngine::examine_identity, (void *)this);
    38         ::log_event(m_session, "Startup", "pEp COM Adapter", NULL, NULL);
    39     }
    40 
    41     ~CpEpEngine()
    42     {
    43         stop_keysync();
    44         StopKeyserverLookup();
    45         ::log_event(m_session, "Shutdown", "pEp COM Adapter", NULL, NULL);
    46         ::release(m_session);
    47     }
    48 
    49 DECLARE_REGISTRY_RESOURCEID(IDR_PEPENGINE)
    50 
    51 DECLARE_NOT_AGGREGATABLE(CpEpEngine)
    52 
    53 BEGIN_COM_MAP(CpEpEngine)
    54     COM_INTERFACE_ENTRY(IpEpEngine)
    55     COM_INTERFACE_ENTRY(IpEpEngine2)
    56     COM_INTERFACE_ENTRY(ISupportErrorInfo)
    57 END_COM_MAP()
    58 
    59 // ISupportsErrorInfo
    60 	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    61 
    62 
    63 	DECLARE_PROTECT_FINAL_CONSTRUCT()
    64 
    65 	HRESULT FinalConstruct()
    66 	{
    67 		return S_OK;
    68 	}
    69 
    70 	void FinalRelease()
    71 	{
    72 	}
    73 
    74 
    75 protected:
    76     class session
    77     {
    78     private:
    79         CpEpEngine *me;
    80 
    81     public:
    82         session(CpEpEngine *myself)
    83         {
    84             me = myself;
    85             me->session_mutex.lock();
    86         }
    87 
    88         ~session()
    89         {
    90             me->session_mutex.unlock();
    91         }
    92 
    93         operator PEP_SESSION const ()
    94         {
    95             return me->m_session;
    96         }
    97     };
    98 
    99     session get_session()
   100     {
   101         return session(this);
   102     }
   103 
   104     typedef locked_queue<pEp_identity_cpp> identity_queue_t;
   105     static ::pEp_identity * retrieve_next_identity(void *management);
   106     static PEP_STATUS messageToSend(void * obj, message *msg);
   107     static PEP_STATUS notifyHandshake(void * obj, pEp_identity *self, pEp_identity *partner, sync_handshake_signal signal);
   108 
   109 
   110     HRESULT error(_bstr_t msg);
   111     HRESULT error(_bstr_t msg, PEP_STATUS errorcode);
   112 
   113     void verbose(string text)
   114     {
   115         if (verbose_mode) {
   116             stringstream ss;
   117             ss << __FILE__ << ":" << __LINE__ << " " << text;
   118             ::log_event(get_session(), "verbose", "pEp COM Server Adapter", ss.str().c_str(), NULL);
   119         }
   120     }
   121 
   122 private:
   123     PEP_SESSION m_session;
   124     mutex session_mutex;
   125     atomic< identity_queue_t * > identity_queue;
   126     thread *keymanagement_thread;
   127     bool verbose_mode;
   128 
   129 	IpEpEngineCallbacks* client_callbacks = NULL;
   130     IpEpEngineCallbacks* client_callbacks_on_sync_thread = NULL;
   131     IpEpEngineCallbacks2* client_callbacks2_on_sync_thread = NULL;
   132     bool client_last_signalled_polling_state = true;
   133 
   134 	// Keysync members
   135     static int inject_sync_msg(void *msg, void* management);
   136     static void* retrieve_next_sync_msg(void* management, time_t *timeout);
   137     void start_keysync();
   138     static void do_keysync_in_thread(CpEpEngine* self, LPSTREAM marshaled_callbacks);
   139     void stop_keysync();
   140 
   141     std::mutex keysync_mutex;
   142     std::condition_variable keysync_condition;
   143     std::thread *keysync_thread = NULL;
   144     std::queue<void*> keysync_queue;
   145     bool keysync_abort_requested = false;
   146     PEP_SESSION keysync_session;
   147 
   148     // Members used for handshake notification dispatch to the background thread.
   149     static void notify_handshake_background_thread(CpEpEngine* self, LPSTREAM marshaled_callbacks);
   150     void notify_handshake_deliver_result();
   151     bool notify_handshake_active = false;
   152     bool notify_handshake_finished = false;
   153     std::thread *notify_handshake_thread = NULL;
   154     pEpIdentity notify_handshake_self;
   155     pEpIdentity notify_handshake_partner;
   156     SyncHandshakeSignal notify_handshake_signal;
   157     SyncHandshakeResult notify_handshake_result;
   158     LPSTREAM notify_handshake_error_info = NULL;
   159     HRESULT notify_handshake_error;
   160 
   161 public:
   162     // runtime config of the adapter
   163 
   164     STDMETHOD(VerboseLogging)(VARIANT_BOOL enable);
   165 
   166     // runtime config of the engine
   167 
   168     STDMETHOD(PassiveMode)(VARIANT_BOOL enable);
   169     STDMETHOD(UnencryptedSubject)(VARIANT_BOOL enable);
   170 
   171     // basic API
   172 
   173     STDMETHOD(ExportKey)(BSTR fpr, BSTR * keyData);
   174     STDMETHOD(Log)(BSTR title, BSTR entity, BSTR description, BSTR comment);
   175     STDMETHOD(Trustwords)(BSTR fpr, BSTR lang, LONG max_words, BSTR * words);
   176     STDMETHOD(GetTrustwords)(struct pEpIdentity *id1, struct pEpIdentity *id2, BSTR lang, VARIANT_BOOL full, BSTR *words);
   177     STDMETHOD(GetMessageTrustwords)(
   178         /* [in] */ struct TextMessage *msg,
   179         /* [in] */ struct pEpIdentity *receivedBy,
   180         /* [in] */ SAFEARRAY *keylist,
   181         /* [defaultvalue][in] */ BSTR lang,
   182         /* [defaultvalue][in] */ VARIANT_BOOL full,
   183         /* [retval][out] */ BSTR *words);
   184     STDMETHOD(GetCrashdumpLog)(LONG maxlines, BSTR * log);
   185     STDMETHOD(GetEngineVersion)(BSTR * engineVersion);
   186     STDMETHOD(GetLanguageList)(BSTR * languages);
   187 	STDMETHOD(SetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
   188 	STDMETHOD(UnsetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
   189 
   190     // keymanagement API
   191 
   192     STDMETHOD(StartKeyserverLookup)();
   193     STDMETHOD(StopKeyserverLookup)();
   194 
   195     STDMETHOD(Myself)(struct pEpIdentity *ident, struct pEpIdentity *result);
   196     STDMETHOD(UpdateIdentity)(struct pEpIdentity *ident, struct pEpIdentity *result);
   197     STDMETHOD(KeyMistrusted)(struct pEpIdentity *ident);
   198     STDMETHOD(KeyResetTrust)(struct pEpIdentity *ident);
   199     STDMETHOD(TrustPersonalKey)(struct pEpIdentity *ident, struct pEpIdentity *result);
   200 	STDMETHOD(OwnIdentitiesRetrieve)(LPSAFEARRAY* own_identities);
   201 
   202     // Blacklist API
   203 
   204     STDMETHOD(BlacklistAdd)(BSTR fpr);
   205     STDMETHOD(BlacklistDelete)(BSTR fpr);
   206     STDMETHOD(BlacklistIsListed)(BSTR fpr, VARIANT_BOOL *listed);
   207     STDMETHOD(BlacklistRetrieve)(SAFEARRAY **blacklist);
   208 
   209     // Message API
   210 
   211     STDMETHOD(EncryptMessage)(TextMessage * src, TextMessage * dst, SAFEARRAY * extra, pEpEncryptFlags flags);
   212     STDMETHOD(DecryptMessage)(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags* flags, pEpRating *rating);
   213     STDMETHOD(OutgoingMessageRating)(TextMessage *msg, pEpRating * pVal);
   214     STDMETHOD(IdentityRating)(pEpIdentity * ident, pEpRating * pVal);
   215 	STDMETHOD(ColorFromRating)(pEpRating rating, pEpColor * pVal);
   216 
   217 	// Event callbacks
   218 
   219 	STDMETHOD(RegisterCallbacks)(IpEpEngineCallbacks *new_callback);
   220 	STDMETHOD(UnregisterCallbacks)();
   221 
   222     // PGP compatibility functions
   223     STDMETHOD(OpenPGPListKeyinfo)(BSTR search_pattern, LPSAFEARRAY* keyinfo_list);
   224 
   225 protected:
   226 	HRESULT Fire_MessageToSend(
   227 		/* [in] */ struct TextMessage *msg);
   228 
   229 	HRESULT Fire_NotifyHandshake(
   230 		/* [in] */ struct pEpIdentity *self,
   231 		/* [in] */ struct pEpIdentity *partner,
   232 		/* [in] */ SyncHandshakeSignal signal,
   233 		/* [retval][out] */ SyncHandshakeResult *result);
   234 };
   235 
   236 OBJECT_ENTRY_AUTO(__uuidof(pEpEngine), CpEpEngine)