CpEpEngine.h
author Volker Birk <vb@pep.foundation>
Mon, 22 Oct 2018 10:14:50 +0200
branchsync
changeset 304 00916b0afaac
parent 297 a48f0545e221
child 307 eb5012d87405
permissions -rw-r--r--
start COM on sync thread
     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 "..\libpEpAdapter\locked_queue.hh"
     8 #include "utf8_helper.h"
     9 #include "pEp_utility.h"
    10 #include "..\libpEpAdapter\Adapter.hh"
    11 #include <queue>
    12 #include <mutex>
    13 #include <vector>
    14 #include "..\libpEpAdapter\pc_container.hh"
    15 
    16 #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
    17 #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."
    18 #endif
    19 
    20 using namespace ATL;
    21 using namespace utility;
    22 using namespace pEp::utility;
    23 using namespace pEp::Adapter;
    24 
    25 // CpEpEngine
    26 
    27 class ATL_NO_VTABLE CpEpEngine :
    28     public CComObjectRootEx<CComObjectThreadModel>,
    29     public CComCoClass<CpEpEngine, &CLSID_pEpEngine>,
    30     public ISupportErrorInfo,
    31     public IpEpEngine
    32 {
    33 
    34 protected:
    35     static int examine_identity(pEp_identity *ident, void *management);
    36 
    37 public:
    38     CpEpEngine() : keymanagement_thread(NULL), identity_queue(NULL), verbose_mode(false)
    39     {
    40         // See FinalConstruct() below for most initialization work, and an
    41         // explanation why it had to be moved there...
    42         ++count;
    43     }
    44 
    45     ~CpEpEngine()
    46     {
    47         --count;
    48         if (!count) {
    49             StopKeyserverLookup();
    50             ::log_event(session(), "Shutdown", "pEp COM Adapter", NULL, NULL);
    51             session(pEp::Adapter::release);
    52             shutdown();
    53         }
    54     }
    55 
    56     DECLARE_REGISTRY_RESOURCEID(IDR_PEPENGINE)
    57 
    58     DECLARE_NOT_AGGREGATABLE(CpEpEngine)
    59 
    60     BEGIN_COM_MAP(CpEpEngine)
    61         COM_INTERFACE_ENTRY(IpEpEngine)
    62         COM_INTERFACE_ENTRY(ISupportErrorInfo)
    63     END_COM_MAP()
    64 
    65     // ISupportsErrorInfo
    66     STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    67 
    68     DECLARE_PROTECT_FINAL_CONSTRUCT()
    69 
    70     // Unfortunately, neither FAIL nor error() work in the constructor, as 
    71     // CreateErrorInfo/SetErrorInfo cannot work when the instance is not constructed.
    72     // AtlThrow works, but the exception is caught in CComCreator.CreateInstance, and
    73     // unconditionally turned into E_OUTOFMEMORY. Thus, we need to do most constructor
    74     // work in FinalConstruct. CreateErrorInfo/SetErrorInfo still won't work, but at least,
    75     // we can return a meaningful HRESULT. Thus, we pack our PEP_STATUS into a custom HRESULT.	
    76     HRESULT FinalConstruct()
    77     {
    78         std::lock_guard<std::mutex> lock(init_mutex);
    79         try {
    80             session();
    81         }
    82         catch (pEp::RuntimeError& e) {
    83             HRESULT res = MAKE_HRESULT(1, FACILITY_ITF, (0xFFFF & e.status));
    84             return res;
    85         }
    86 
    87         ::register_examine_function(session(), CpEpEngine::examine_identity, (void *)this);
    88         ::log_event(session(), "Startup", "pEp COM Adapter", NULL, NULL);
    89 
    90         startup<CpEpEngine>(messageToSend, notifyHandshake, messageToSend_sync, notifyHandshake_sync, this, &CpEpEngine::Startup_sync);
    91 
    92         return S_OK;
    93     }
    94 
    95     void FinalRelease()
    96     {
    97     }
    98 
    99 protected:
   100     typedef locked_queue<pEp_identity_cpp> identity_queue_t;
   101     static ::pEp_identity * retrieve_next_identity(void *management);
   102 
   103     static PEP_STATUS _messageToSend(message *msg, bool in_sync = false);
   104     static PEP_STATUS _notifyHandshake(pEp_identity *self, pEp_identity *partner, sync_handshake_signal signal, bool in_sync = false);
   105 
   106     static PEP_STATUS messageToSend(message *msg);
   107     static PEP_STATUS notifyHandshake(pEp_identity *self, pEp_identity *partner, sync_handshake_signal signal);
   108 
   109     static PEP_STATUS messageToSend_sync(message *msg);
   110     static PEP_STATUS notifyHandshake_sync(pEp_identity *self, pEp_identity *partner, sync_handshake_signal signal);
   111 
   112     HRESULT error(_bstr_t msg);
   113     HRESULT error(_bstr_t msg, PEP_STATUS errorcode);
   114 
   115     void verbose(string text)
   116     {
   117         if (verbose_mode) {
   118             stringstream ss;
   119             ss << __FILE__ << ":" << __LINE__ << " " << text;
   120             ::log_event(session(), "verbose", "pEp COM Server Adapter", ss.str().c_str(), NULL);
   121         }
   122     }
   123 
   124 private:
   125     // callbacks for sync
   126     struct MarshaledCallbacks {
   127         IpEpEngineCallbacks *unmarshaled;
   128         LPSTREAM marshaled;
   129     };
   130 
   131     static pEp::pc_container< MarshaledCallbacks, IpEpEngineCallbacks > sync_callbacks;
   132 
   133     void Startup_sync()
   134     {
   135         HRESULT r = CoInitializeEx(NULL, COINIT_MULTITHREADED);
   136         if (!SUCCEEDED(r))
   137             throw runtime_error("CoInitializeEx() failed on sync thread");
   138     }
   139 
   140     atomic< identity_queue_t * > identity_queue;
   141     thread *keymanagement_thread;
   142     bool verbose_mode;
   143 
   144     IpEpEngineCallbacks* client_callbacks = NULL;
   145     bool client_last_signalled_polling_state = true;
   146 
   147     static std::mutex init_mutex;
   148     static atomic< int > count;
   149 
   150 public:
   151     // runtime config of the adapter
   152 
   153     STDMETHOD(VerboseLogging)(VARIANT_BOOL enable);
   154 
   155     // runtime config of the engine
   156 
   157     STDMETHOD(PassiveMode)(VARIANT_BOOL enable);
   158     STDMETHOD(UnencryptedSubject)(VARIANT_BOOL enable);
   159 
   160     // basic API
   161 
   162     STDMETHOD(ExportKey)(BSTR fpr, BSTR * keyData);
   163     STDMETHOD(Log)(BSTR title, BSTR entity, BSTR description, BSTR comment);
   164     STDMETHOD(Trustwords)(BSTR fpr, BSTR lang, LONG max_words, BSTR * words);
   165     STDMETHOD(GetTrustwords)(struct pEpIdentity *id1, struct pEpIdentity *id2, BSTR lang, VARIANT_BOOL full, BSTR *words);
   166     STDMETHOD(GetMessageTrustwords)(
   167         /* [in] */ struct TextMessage *msg,
   168         /* [in] */ struct pEpIdentity *receivedBy,
   169         /* [in] */ SAFEARRAY *keylist,
   170         /* [defaultvalue][in] */ BSTR lang,
   171         /* [defaultvalue][in] */ VARIANT_BOOL full,
   172         /* [retval][out] */ BSTR *words);
   173     STDMETHOD(GetCrashdumpLog)(LONG maxlines, BSTR * log);
   174     STDMETHOD(GetEngineVersion)(BSTR * engineVersion);
   175     STDMETHOD(GetLanguageList)(BSTR * languages);
   176     STDMETHOD(SetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
   177     STDMETHOD(UnsetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
   178 
   179     // keymanagement API
   180 
   181     STDMETHOD(StartKeyserverLookup)();
   182     STDMETHOD(StopKeyserverLookup)();
   183 
   184     STDMETHOD(Myself)(struct pEpIdentity *ident, struct pEpIdentity *result);
   185     STDMETHOD(UpdateIdentity)(struct pEpIdentity *ident, struct pEpIdentity *result);
   186     STDMETHOD(KeyMistrusted)(struct pEpIdentity *ident);
   187     STDMETHOD(KeyResetTrust)(struct pEpIdentity *ident);
   188     STDMETHOD(TrustPersonalKey)(struct pEpIdentity *ident, struct pEpIdentity *result);
   189     STDMETHOD(OwnIdentitiesRetrieve)(LPSAFEARRAY* ownIdentities);
   190 
   191     // STDMETHOD(UndoLastMistrust)(); 
   192     
   193     STDMETHOD(IspEpUser)(
   194         /* [in] */ struct pEpIdentity *ident,
   195         /* [retval][out] */ VARIANT_BOOL *ispEp);
   196 
   197     // Blacklist API
   198 
   199     STDMETHOD(BlacklistAdd)(BSTR fpr);
   200     STDMETHOD(BlacklistDelete)(BSTR fpr);
   201     STDMETHOD(BlacklistIsListed)(BSTR fpr, VARIANT_BOOL *listed);
   202     STDMETHOD(BlacklistRetrieve)(SAFEARRAY **blacklist);
   203 
   204     // Message API
   205 
   206     STDMETHOD(EncryptMessage)(
   207         /* [in] */ struct TextMessage *src,
   208         /* [out] */ struct TextMessage *dst,
   209         /* [in] */ SAFEARRAY * extra,
   210         /* [defaultvalue][in] */ pEpEncryptFlags flags = pEpEncryptFlagDefault,
   211         /* [defaultvalue][in] */ pEpEncFormat encFormat = pEpEncPep);
   212 
   213     STDMETHOD(EncryptMessageAndAddPrivKey)(
   214         /* [in] */ struct TextMessage *src,
   215         /* [out] */ struct TextMessage *dst,
   216         /* [in] */ BSTR to_fpr,
   217         /* [defaultvalue][in] */ pEpEncryptFlags flags = pEpEncryptFlagDefault,
   218         /* [defaultvalue][in] */ pEpEncFormat encFormat = pEpEncPep);
   219 
   220     STDMETHOD(DecryptMessage)(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags* flags, pEpRating *rating);
   221     STDMETHOD(ReEvaluateMessageRating)(TextMessage * msg, SAFEARRAY * x_KeyList, pEpRating x_EncStatus, pEpRating *rating);
   222 	STDMETHOD(OutgoingMessageRating)(TextMessage *msg, pEpRating * pVal);
   223 	STDMETHOD(OutgoingMessageRatingPreview)(TextMessage *msg, pEpRating * pVal);
   224     STDMETHOD(IdentityRating)(pEpIdentity * ident, pEpRating * pVal);
   225     STDMETHOD(ColorFromRating)(pEpRating rating, pEpColor * pVal);
   226 
   227     STDMETHOD(EncryptMessageForSelf)(
   228         pEpIdentity * targetId,
   229         TextMessage* src,
   230         /* [in] */ SAFEARRAY *extra,
   231         TextMessage *dst,
   232         pEpEncryptFlags flags
   233         );
   234 
   235     // Event callbacks
   236 
   237     STDMETHOD(RegisterCallbacks)(IpEpEngineCallbacks *new_callback);
   238     STDMETHOD(UnregisterCallbacks)();
   239 
   240     // PGP compatibility functions
   241     STDMETHOD(OpenPGPListKeyinfo)(BSTR search_pattern, LPSAFEARRAY* keyinfo_list);
   242 	STDMETHOD(SetOwnKey)(pEpIdentity * ident, BSTR fpr, struct pEpIdentity *result);
   243 
   244     // Trigger an immediate update
   245     STDMETHOD(UpdateNow)();
   246 };
   247 
   248 OBJECT_ENTRY_AUTO(__uuidof(pEpEngine), CpEpEngine)