From 600f344d88bec6dd61aa123be1d2114bffbdf493 Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Thu, 17 Aug 2017 20:26:39 +0300 Subject: jabber: omemo: working on TODO implemented message queue for messages received/sendt before omemo sessions created //this solve problem with loosing first message --- protocols/JabberG/src/jabber_omemo.cpp | 106 +++++++++++++++++++++++++----- protocols/JabberG/src/jabber_omemo.h | 2 + protocols/JabberG/src/jabber_opt.cpp | 1 + protocols/JabberG/src/jabber_proto.cpp | 10 +-- protocols/JabberG/src/jabber_proto.h | 5 +- protocols/JabberG/src/jabber_thread.cpp | 2 +- protocols/JabberG/src/jabber_userinfo.cpp | 1 + 7 files changed, 106 insertions(+), 21 deletions(-) mode change 100644 => 100755 protocols/JabberG/src/jabber_userinfo.cpp diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index 424055d947..6d5814649e 100755 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -26,9 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //TODO: further improovement requirements folllows in priority sequence /* 1. fix AES-128 GCM in 4.5 implementation * 2. handle prekeys properly (cleanup after first use, create new keys) - * 3. reimplement session initialization without loosing first message (incomming + outgoing) - * 4. fingerprints/keys management ui - * 5. per-contact encryption settings (enable/disable for one contact) + * 3. fingerprints/keys management ui + * 4. per-contact encryption settings (enable/disable for one contact) */ #include "stdafx.h" @@ -396,6 +395,39 @@ namespace omemo { signal_context *global_context = nullptr; + + struct incomming_message + { + incomming_message(HXML x, wchar_t *j, time_t t) + { + node = x; + jid = j; + msgTime = t; + } + HXML node; + wchar_t *jid; + time_t msgTime; + }; + + struct outgoing_message + { + outgoing_message(MCONTACT h, int u, char* p) + { + hContact = h; + unused_unknown = u; + pszSrc = p; + } + MCONTACT hContact; + int unused_unknown; + char* pszSrc; + }; + + struct message_queue + { + std::list incomming_messages; + std::list outgoing_messages; + }; + struct omemo_session_jabber_internal_ptrs { session_builder *builder; @@ -442,6 +474,8 @@ namespace omemo { //TODO: handle error } sessions_internal = new std::map >; + message_queue_internal = new message_queue; + session_checked = new std::map; } omemo_impl::~omemo_impl() { @@ -471,6 +505,8 @@ namespace omemo { delete (std::map >*)sessions_internal; delete signal_mutex; delete provider; + delete message_queue_internal; + delete session_checked; provider = nullptr; signal_mutex = nullptr; } @@ -1418,10 +1454,10 @@ namespace omemo { mir_free(key_buf); //TODO: check this bool fp_trusted = false; { //check fingerprint - signal_buffer *key_buf; - ec_public_key_serialize(&key_buf, identity_key_p); - char *fingerprint = (char*)mir_alloc((signal_buffer_len(key_buf) * 2) + 1); - bin2hex(signal_buffer_data(key_buf), signal_buffer_len(key_buf), fingerprint); + signal_buffer *key_buf2; + ec_public_key_serialize(&key_buf2, identity_key_p); + char *fingerprint = (char*)mir_alloc((signal_buffer_len(key_buf2) * 2) + 1); + bin2hex(signal_buffer_data(key_buf2), signal_buffer_len(key_buf2), fingerprint); const size_t setting_name_len = strlen("OmemoFingerprintTrusted_") + strlen(fingerprint) + 1; char *fp_setting_name = (char*)mir_alloc(setting_name_len); @@ -1507,14 +1543,48 @@ void CJabberProto::OmemoInitDevice() m_omemo.RefreshDevice(); } +void CJabberProto::OmemoPutMessageToOutgoingQueue(MCONTACT hContact, int unused_unknown, const char* pszSrc) +{ + char *msg = mir_strdup(pszSrc); + ((omemo::message_queue*)m_omemo.message_queue_internal)->outgoing_messages.push_back(omemo::outgoing_message(hContact, unused_unknown, msg)); +} + +void CJabberProto::OmemoPutMessageToIncommingQueue(HXML node, LPCTSTR jid, time_t msgTime) +{ + wchar_t *jid_ = mir_wstrdup(jid); + HXML node_ = xmlCopyNode(node); + ((omemo::message_queue*)m_omemo.message_queue_internal)->incomming_messages.push_back(omemo::incomming_message(node_, jid_, msgTime)); + +} + +void CJabberProto::OmemoHandleMessageQueue() +{ + for (std::list::iterator i = ((omemo::message_queue*)m_omemo.message_queue_internal)->outgoing_messages.begin(), + end = ((omemo::message_queue*)m_omemo.message_queue_internal)->outgoing_messages.end(); i != end; ++i) + { + SendMsg(i->hContact, i->unused_unknown, i->pszSrc); + mir_free(i->pszSrc); + } + ((omemo::message_queue*)m_omemo.message_queue_internal)->outgoing_messages.clear(); + for (std::list::iterator i = ((omemo::message_queue*)m_omemo.message_queue_internal)->incomming_messages.begin(), + end = ((omemo::message_queue*)m_omemo.message_queue_internal)->incomming_messages.end(); i != end; ++i) + { + OmemoHandleMessage(i->node, i->jid, i->msgTime); + xmlFree(i->node); + mir_free(i->jid); + } + ((omemo::message_queue*)m_omemo.message_queue_internal)->incomming_messages.clear(); +} + DWORD JabberGetLastContactMessageTime(MCONTACT hContact); -void CJabberProto::OmemoHandleMessage(HXML node, LPCTSTR jid, time_t msgTime) +void CJabberProto::OmemoHandleMessage(HXML node, wchar_t *jid, time_t msgTime) { MCONTACT hContact = HContactFromJID(jid); - if (!OmemoCheckSession(hContact)) //TODO: something better here + if (!OmemoCheckSession(hContact)) { - debugLogA("Jabber OMEMO: sessions not yet created, session creation launched, message will not be decrypted"); + OmemoPutMessageToIncommingQueue(node, jid, msgTime); + debugLogA("Jabber OMEMO: sessions not yet created, session creation launched"); return; } HXML header_node = XmlGetChild(node, L"header"); @@ -1554,8 +1624,9 @@ void CJabberProto::OmemoHandleMessage(HXML node, LPCTSTR jid, time_t msgTime) || !(*(std::map >*)m_omemo.sessions_internal)[hContact][sender_dev_id_int].builder || !(*(std::map >*)m_omemo.sessions_internal)[hContact][sender_dev_id_int].store_context) { - debugLogA("Jabber OMEMO: bug: omemo session does not exist or broken"); OmemoCheckSession(hContact); //this should not normally happened + OmemoPutMessageToIncommingQueue(node, jid, msgTime); + debugLogA("Jabber OMEMO: bug: omemo session does not exist or broken"); return; } HXML key_node; @@ -1977,8 +2048,8 @@ void CJabberProto::OmemoPublishNodes() bool CJabberProto::OmemoCheckSession(MCONTACT hContact) { -/* if (getBool(hContact, "OmemoSessionChecked")) - return true; */ + if ((*(std::map*)m_omemo.session_checked)[hContact]) + return true; bool pending_check = false; char setting_name[64], setting_name2[64]; @@ -2009,6 +2080,7 @@ bool CJabberProto::OmemoCheckSession(MCONTACT hContact) XmlAddAttr(items, L"node", bundle); m_ThreadInfo->send(iq); mir_free(jid); + break; } i++; mir_snprintf(setting_name, "OmemoDeviceId%d", i); @@ -2018,9 +2090,13 @@ bool CJabberProto::OmemoCheckSession(MCONTACT hContact) } if (!pending_check) + { + (*(std::map*)m_omemo.session_checked)[hContact] = true; + OmemoHandleMessageQueue(); return true; + } else - debugLogA("Jabber OMEMO: info: OmemoCheckSession: pending session creation encryption/decryption of THIS message will not be done and message WILL be lost"); + debugLogA("Jabber OMEMO: info: OmemoCheckSession: pending session creation"); return false; } @@ -2179,7 +2255,7 @@ void CJabberProto::OmemoOnIqResultGetBundle(HXML iqNode, CJabberIqInfo *pInfo) id = getDword(hContact, setting_name, 0); } } - + OmemoCheckSession(hContact); } diff --git a/protocols/JabberG/src/jabber_omemo.h b/protocols/JabberG/src/jabber_omemo.h index 28d765309c..16e063e6ec 100755 --- a/protocols/JabberG/src/jabber_omemo.h +++ b/protocols/JabberG/src/jabber_omemo.h @@ -23,6 +23,8 @@ namespace omemo { mir_cslockfull *signal_mutex; void *sessions_internal; + void *session_checked; + void *message_queue_internal; private: CJabberProto *proto; mir_cs _signal_cs; diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp index e7188ec358..406cd96227 100755 --- a/protocols/JabberG/src/jabber_opt.cpp +++ b/protocols/JabberG/src/jabber_opt.cpp @@ -1510,6 +1510,7 @@ int CJabberProto::OnOptionsInit(WPARAM wParam, LPARAM) odp.szTab.w = LPGENW("Advanced"); odp.pDialog = new CDlgOptAdvanced(this); Options_AddPage(wParam, &odp); + //TODO: add omemo options return 0; } diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 2b587e2415..cba4d8cdeb 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -905,7 +905,7 @@ void __cdecl CJabberProto::SendMessageAckThread(void* param) static char PGP_PROLOG[] = "-----BEGIN PGP MESSAGE-----\r\n\r\n"; static char PGP_EPILOG[] = "\r\n-----END PGP MESSAGE-----\r\n"; -int __cdecl CJabberProto::SendMsg(MCONTACT hContact, int, const char* pszSrc) +int __cdecl CJabberProto::SendMsg(MCONTACT hContact, int unused_unknown, const char* pszSrc) { wchar_t szClientJid[JABBER_MAX_JID_LEN]; if (!m_bJabberOnline || !GetClientJID(hContact, szClientJid, _countof(szClientJid))) { @@ -916,11 +916,13 @@ int __cdecl CJabberProto::SendMsg(MCONTACT hContact, int, const char* pszSrc) if (m_options.UseOMEMO) { - if (!OmemoCheckSession(hContact)) //check omemo session state and build new session if necessary //TODO: something better + if (!OmemoCheckSession(hContact)) { - TFakeAckParams *param = new TFakeAckParams(hContact, Translate("OMEMO session does not exist yet")); + OmemoPutMessageToOutgoingQueue(hContact, unused_unknown, pszSrc); + int id = SerialNext(); + TFakeAckParams *param = new TFakeAckParams(hContact, 0, id); ForkThread(&CJabberProto::SendMessageAckThread, param); - return 0; + return id; } } diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index 7822b06bee..a58a07ac8f 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -340,7 +340,10 @@ struct CJabberProto : public PROTO, public IJabberInterface void DeleteMucListItem(JABBER_MUC_JIDLIST_INFO* jidListInfo, const wchar_t* jid); //---- jabber_omemo.cpp -------------------------------------------------------------- - void OmemoHandleMessage(HXML node, LPCTSTR jid, time_t msgTime); + void OmemoHandleMessage(HXML node, wchar_t *jid, time_t msgTime); + void OmemoPutMessageToOutgoingQueue(MCONTACT hContact, int, const char* pszSrc); + void OmemoPutMessageToIncommingQueue(HXML node, LPCTSTR jid, time_t msgTime); + void OmemoHandleMessageQueue(); void OmemoHandleDeviceList(HXML node); void OmemoInitDevice(); void OmemoAnnounceDevice(); diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index eef8392df4..a5a7945a41 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -1206,7 +1206,7 @@ void CJabberProto::OnProcessMessage(HXML node, ThreadData *info) LPCTSTR jid = xmlGetAttrValue(node, L"from"); if (jid) { - OmemoHandleMessage(xNode, jid, msgTime); + OmemoHandleMessage(xNode, (wchar_t*)jid, msgTime); continue; } } diff --git a/protocols/JabberG/src/jabber_userinfo.cpp b/protocols/JabberG/src/jabber_userinfo.cpp old mode 100644 new mode 100755 index 7079c8a5c6..92498413e5 --- a/protocols/JabberG/src/jabber_userinfo.cpp +++ b/protocols/JabberG/src/jabber_userinfo.cpp @@ -834,6 +834,7 @@ int CJabberProto::OnUserInfoInit(WPARAM wParam, LPARAM lParam) odp.szTitle.a = LPGEN("Photo"); UserInfo_AddPage(wParam, &odp); } + //TODO: add omemo dialog to userinfo return 0; } -- cgit v1.2.3