CpEpEngine.h
author Thomas
Wed, 02 May 2018 09:46:48 +0200
branchCOM-87
changeset 287 99abd7d70c1e
parent 284 83ad8d765099
child 292 2c8123bded5a
permissions -rw-r--r--
Rename flags
     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 #include <mutex>
    12 
    13 #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
    14 #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."
    15 #endif
    16 
    17 using namespace ATL;
    18 using namespace utility;
    19 using namespace pEp::utility;
    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 IpEpEngine
    28 {
    29 
    30 protected:
    31     static int examine_identity(pEp_identity *ident, void *management);
    32 
    33 public:
    34     CpEpEngine() : keymanagement_thread(NULL), identity_queue(NULL), verbose_mode(false)
    35     {
    36         // See FinalConstruct() below for most initialization work, and an
    37         // explanation why it had to be moved there...
    38     }
    39 
    40     ~CpEpEngine()
    41     {
    42         stop_keysync();
    43         StopKeyserverLookup();
    44         if (m_session) // may be zero when FinalConstruct failed to initialize the engine
    45         {
    46             ::log_event(m_session, "Shutdown", "pEp COM Adapter", NULL, NULL);
    47             std::lock_guard<std::mutex> lock(init_mutex);
    48             ::release(m_session);
    49         }
    50     }
    51 
    52     DECLARE_REGISTRY_RESOURCEID(IDR_PEPENGINE)
    53 
    54     DECLARE_NOT_AGGREGATABLE(CpEpEngine)
    55 
    56     BEGIN_COM_MAP(CpEpEngine)
    57         COM_INTERFACE_ENTRY(IpEpEngine)
    58         COM_INTERFACE_ENTRY(ISupportErrorInfo)
    59     END_COM_MAP()
    60 
    61     // ISupportsErrorInfo
    62     STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    63 
    64     DECLARE_PROTECT_FINAL_CONSTRUCT()
    65 
    66     // Unfortunately, neither FAIL nor error() work in the constructor, as 
    67     // CreateErrorInfo/SetErrorInfo cannot work when the instance is not constructed.
    68     // AtlThrow works, but the exception is caught in CComCreator.CreateInstance, and
    69     // unconditionally turned into E_OUTOFMEMORY. Thus, we need to do most constructor
    70     // work in FinalConstruct. CreateErrorInfo/SetErrorInfo still won't work, but at least,
    71     // we can return a meaningful HRESULT. Thus, we pack our PEP_STATUS into a custom HRESULT.	
    72     HRESULT FinalConstruct()
    73     {
    74         std::lock_guard<std::mutex> lock(init_mutex);
    75         PEP_STATUS status = ::init(&m_session);
    76         assert(status == PEP_STATUS_OK);
    77         if (status != PEP_STATUS_OK) {
    78             HRESULT res = MAKE_HRESULT(1, FACILITY_ITF, (0xFFFF & status));
    79             return res;
    80         }
    81 
    82         ::register_examine_function(m_session, CpEpEngine::examine_identity, (void *)this);
    83         ::log_event(m_session, "Startup", "pEp COM Adapter", NULL, NULL);
    84         return S_OK;
    85     }
    86 
    87     void FinalRelease()
    88     {
    89     }
    90 
    91 
    92 protected:
    93     class session
    94     {
    95     private:
    96         CpEpEngine *me;
    97 
    98     public:
    99         session(CpEpEngine *myself)
   100         {
   101             me = myself;
   102             me->session_mutex.lock();
   103         }
   104 
   105         ~session()
   106         {
   107             me->session_mutex.unlock();
   108         }
   109 
   110         operator PEP_SESSION const ()
   111         {
   112             return me->m_session;
   113         }
   114     };
   115 
   116     session get_session()
   117     {
   118         return session(this);
   119     }
   120 
   121     typedef locked_queue<pEp_identity_cpp> identity_queue_t;
   122     static ::pEp_identity * retrieve_next_identity(void *management);
   123     static PEP_STATUS messageToSend(void * obj, message *msg);
   124     static PEP_STATUS notifyHandshake(void * obj, pEp_identity *self, pEp_identity *partner, sync_handshake_signal signal);
   125 
   126 
   127     HRESULT error(_bstr_t msg);
   128     HRESULT error(_bstr_t msg, PEP_STATUS errorcode);
   129 
   130     void verbose(string text)
   131     {
   132         if (verbose_mode) {
   133             stringstream ss;
   134             ss << __FILE__ << ":" << __LINE__ << " " << text;
   135             ::log_event(get_session(), "verbose", "pEp COM Server Adapter", ss.str().c_str(), NULL);
   136         }
   137     }
   138 
   139 private:
   140     PEP_SESSION m_session;
   141     mutex session_mutex;
   142     atomic< identity_queue_t * > identity_queue;
   143     thread *keymanagement_thread;
   144     bool verbose_mode;
   145 
   146 
   147     IpEpEngineCallbacks* client_callbacks = NULL;
   148     IpEpEngineCallbacks* client_callbacks_on_sync_thread = NULL;
   149     bool client_last_signalled_polling_state = true;
   150 
   151     // Keysync members
   152     static int inject_sync_msg(void *msg, void* management);
   153     static void* retrieve_next_sync_msg(void* management, time_t *timeout);
   154     void start_keysync();
   155     static void do_keysync_in_thread(CpEpEngine* self, LPSTREAM marshaled_callbacks);
   156     void stop_keysync();
   157 
   158     static std::mutex init_mutex;
   159 
   160     std::recursive_mutex keysync_mutex;
   161     std::condition_variable_any keysync_condition;
   162     std::thread *keysync_thread = NULL;
   163     std::queue<void*> keysync_queue;
   164     bool keysync_abort_requested = false;
   165     PEP_SESSION keysync_session;
   166 
   167     // Members used for handshake notification dispatch to the background thread.
   168     static void notify_handshake_background_thread(CpEpEngine* self, LPSTREAM marshaled_callbacks);
   169     void notify_handshake_deliver_result();
   170     bool notify_handshake_active = false;
   171     bool notify_handshake_finished = false;
   172     std::thread *notify_handshake_thread = NULL;
   173     pEpIdentity notify_handshake_self;
   174     pEpIdentity notify_handshake_partner;
   175     SyncHandshakeSignal notify_handshake_signal;
   176     SyncHandshakeResult notify_handshake_result;
   177     LPSTREAM notify_handshake_error_info = NULL;
   178     HRESULT notify_handshake_error;
   179 
   180 public:
   181     // runtime config of the adapter
   182 
   183     STDMETHOD(VerboseLogging)(VARIANT_BOOL enable);
   184 
   185     // runtime config of the engine
   186 
   187     STDMETHOD(PassiveMode)(VARIANT_BOOL enable);
   188     STDMETHOD(UnencryptedSubject)(VARIANT_BOOL enable);
   189 
   190     // basic API
   191 
   192     STDMETHOD(ExportKey)(BSTR fpr, BSTR * keyData);
   193     STDMETHOD(Log)(BSTR title, BSTR entity, BSTR description, BSTR comment);
   194     STDMETHOD(Trustwords)(BSTR fpr, BSTR lang, LONG max_words, BSTR * words);
   195     STDMETHOD(GetTrustwords)(struct pEpIdentity *id1, struct pEpIdentity *id2, BSTR lang, VARIANT_BOOL full, BSTR *words);
   196     STDMETHOD(GetMessageTrustwords)(
   197         /* [in] */ struct TextMessage *msg,
   198         /* [in] */ struct pEpIdentity *receivedBy,
   199         /* [in] */ SAFEARRAY *keylist,
   200         /* [defaultvalue][in] */ BSTR lang,
   201         /* [defaultvalue][in] */ VARIANT_BOOL full,
   202         /* [retval][out] */ BSTR *words);
   203     STDMETHOD(GetCrashdumpLog)(LONG maxlines, BSTR * log);
   204     STDMETHOD(GetEngineVersion)(BSTR * engineVersion);
   205     STDMETHOD(GetLanguageList)(BSTR * languages);
   206     STDMETHOD(SetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
   207     STDMETHOD(UnsetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
   208 
   209     // keymanagement API
   210 
   211     STDMETHOD(StartKeyserverLookup)();
   212     STDMETHOD(StopKeyserverLookup)();
   213 
   214     STDMETHOD(Myself)(struct pEpIdentity *ident, struct pEpIdentity *result);
   215     STDMETHOD(UpdateIdentity)(struct pEpIdentity *ident, struct pEpIdentity *result);
   216     STDMETHOD(KeyMistrusted)(struct pEpIdentity *ident);
   217     STDMETHOD(KeyResetTrust)(struct pEpIdentity *ident);
   218     STDMETHOD(TrustPersonalKey)(struct pEpIdentity *ident, struct pEpIdentity *result);
   219     STDMETHOD(OwnIdentitiesRetrieve)(LPSAFEARRAY* ownIdentities);
   220 
   221     STDMETHOD(UndoLastMistrust)(); 
   222     
   223     STDMETHOD(IsPepUser)(
   224         /* [in] */ struct pEpIdentity *ident,
   225         /* [retval][out] */ VARIANT_BOOL *ispEp);
   226 
   227     // Blacklist API
   228 
   229     STDMETHOD(BlacklistAdd)(BSTR fpr);
   230     STDMETHOD(BlacklistDelete)(BSTR fpr);
   231     STDMETHOD(BlacklistIsListed)(BSTR fpr, VARIANT_BOOL *listed);
   232     STDMETHOD(BlacklistRetrieve)(SAFEARRAY **blacklist);
   233 
   234     // Message API
   235 
   236     STDMETHOD(EncryptMessage)(
   237         /* [in] */ struct TextMessage *src,
   238         /* [out] */ struct TextMessage *dst,
   239         /* [in] */ SAFEARRAY * extra,
   240         /* [defaultvalue][in] */ pEpEncryptFlags flags = pEpEncryptFlagDefault,
   241         /* [defaultvalue][in] */ pEpEncFormat encFormat = pEpEncPep);
   242 
   243     STDMETHOD(EncryptMessageAndAddPrivKey)(
   244         /* [in] */ struct TextMessage *src,
   245         /* [out] */ struct TextMessage *dst,
   246         /* [in] */ BSTR to_fpr,
   247         /* [defaultvalue][in] */ pEpEncryptFlags flags = pEpEncryptFlagDefault,
   248         /* [defaultvalue][in] */ pEpEncFormat encFormat = pEpEncPep);
   249 
   250     STDMETHOD(DecryptMessage)(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags* flags, pEpRating *rating);
   251     STDMETHOD(ReEvaluateMessageRating)(TextMessage * msg, SAFEARRAY * x_KeyList, pEpRating x_EncStatus, pEpRating *rating);
   252     STDMETHOD(OutgoingMessageRating)(TextMessage *msg, pEpRating * pVal);
   253     STDMETHOD(IdentityRating)(pEpIdentity * ident, pEpRating * pVal);
   254     STDMETHOD(ColorFromRating)(pEpRating rating, pEpColor * pVal);
   255 
   256     STDMETHOD(EncryptMessageForSelf)(
   257         pEpIdentity * targetId,
   258         TextMessage* src,
   259         /* [in] */ SAFEARRAY *extra,
   260         TextMessage *dst,
   261         pEpEncryptFlags flags
   262         );
   263 
   264     // Event callbacks
   265 
   266     STDMETHOD(RegisterCallbacks)(IpEpEngineCallbacks *new_callback);
   267     STDMETHOD(UnregisterCallbacks)();
   268 
   269     // PGP compatibility functions
   270     STDMETHOD(OpenPGPListKeyinfo)(BSTR search_pattern, LPSAFEARRAY* keyinfo_list);
   271 	STDMETHOD(SetOwnKey)(pEpIdentity * ident, BSTR fpr, struct pEpIdentity *result);
   272 
   273     // Trigger an immediate update
   274     STDMETHOD(UpdateNow)();
   275 protected:
   276     HRESULT Fire_MessageToSend(
   277         /* [in] */ struct TextMessage *msg);
   278 };
   279 
   280 OBJECT_ENTRY_AUTO(__uuidof(pEpEngine), CpEpEngine)