diff options
author | George Hazan <ghazan@miranda.im> | 2022-10-21 18:43:06 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-10-21 18:43:06 +0300 |
commit | 8a406120d56f454a20db346707fac5dd112b1ccb (patch) | |
tree | 144e7f6243fb9a7fc447fd1dadb0ae25f2f56e5a /protocols/WhatsApp/src | |
parent | f565cc4efeace9a9f1c034f3956bd7192382bea7 (diff) |
WhatsApp: minor fixes & code reordering
Diffstat (limited to 'protocols/WhatsApp/src')
-rw-r--r-- | protocols/WhatsApp/src/appsync.cpp | 1 | ||||
-rw-r--r-- | protocols/WhatsApp/src/iq.cpp | 195 | ||||
-rw-r--r-- | protocols/WhatsApp/src/message.cpp | 165 | ||||
-rw-r--r-- | protocols/WhatsApp/src/proto.h | 3 | ||||
-rw-r--r-- | protocols/WhatsApp/src/server.cpp | 8 |
5 files changed, 192 insertions, 180 deletions
diff --git a/protocols/WhatsApp/src/appsync.cpp b/protocols/WhatsApp/src/appsync.cpp index 9728eae48c..9785dbff65 100644 --- a/protocols/WhatsApp/src/appsync.cpp +++ b/protocols/WhatsApp/src/appsync.cpp @@ -50,7 +50,6 @@ void WhatsAppProto::OnServerSync(const WANode &node) void WhatsAppProto::ResyncAll() { - setDword("lastResyncTime", time(0)); ResyncServer(m_arCollections); } diff --git a/protocols/WhatsApp/src/iq.cpp b/protocols/WhatsApp/src/iq.cpp index c0a2c414ac..258b466ac3 100644 --- a/protocols/WhatsApp/src/iq.cpp +++ b/protocols/WhatsApp/src/iq.cpp @@ -30,6 +30,8 @@ void WhatsAppProto::OnIqBlockList(const WANode &node) void WhatsAppProto::OnIqCountPrekeys(const WANode &node) { + m_bUpdatedPrekeys = true; + int iCount = node.getChild("count")->getAttrInt("value"); if (iCount < 5) UploadMorePrekeys(); @@ -78,191 +80,39 @@ void WhatsAppProto::OnIqDoNothing(const WANode &) ///////////////////////////////////////////////////////////////////////////////////////// -void WhatsAppProto::OnNotifyEncrypt(const WANode &node) +void WhatsAppProto::OnNotifyDevices(const WANode &node) { - auto *pszFrom = node.getAttr("from"); - if (!mir_strcmp(pszFrom, S_WHATSAPP_NET)) { - - } + if (!mir_strcmp(node.getAttr("jid"), m_szJid)) + debugLogA("received list of my own devices"); } ///////////////////////////////////////////////////////////////////////////////////////// -void WhatsAppProto::OnReceiveInfo(const WANode &node) +void WhatsAppProto::OnNotifyEncrypt(const WANode &node) { - if (auto *pChild = node.getFirstChild()) { - if (pChild->title == "offline") { - debugLogA("Processed %d offline events", pChild->getAttrInt("count")); - - if (getDword("lastResyncTime") == 0) { - m_impl.m_resyncApp.Stop(); - m_impl.m_resyncApp.Start(1000); - } - } - } + if (!mir_strcmp(node.getAttr("from"), S_WHATSAPP_NET)) + OnIqCountPrekeys(node); } ///////////////////////////////////////////////////////////////////////////////////////// -void WhatsAppProto::OnReceiveMessage(const WANode &node) +void WhatsAppProto::OnReceiveInfo(const WANode &node) { - auto *msgId = node.getAttr("id"); - auto *msgType = node.getAttr("type"); - auto *msgFrom = node.getAttr("from"); - auto *category = node.getAttr("category"); - auto *recipient = node.getAttr("recipient"); - auto *participant = node.getAttr("participant"); - - if (msgType == nullptr || msgFrom == nullptr || msgId == nullptr) { - debugLogA("bad message received: <%s> <%s> <%s>", msgType, msgFrom, msgId); - return; - } - - WAMSG type; - WAJid jid(msgFrom); - CMStringA szAuthor, szChatId; - - if (node.getAttr("offline")) - type.bOffline = true; - - // message from one user to another - if (jid.isUser()) { - if (recipient) { - if (m_szJid != msgFrom) { - debugLogA("strange message: with recipient, but not from me"); - return; - } - szChatId = recipient; - } - else szChatId = msgFrom; - - type.bPrivateChat = true; - szAuthor = msgFrom; - } - else if (jid.isGroup()) { - if (!participant) { - debugLogA("strange message: from group, but without participant"); - return; - } - - type.bGroupChat = true; - szAuthor = participant; - szChatId = msgFrom; - } - else if (jid.isBroadcast()) { - if (!participant) { - debugLogA("strange message: from group, but without participant"); - return; - } - - bool bIsMe = m_szJid == participant; - if (jid.isStatusBroadcast()) { - if (bIsMe) - type.bDirectStatus = true; - else - type.bOtherStatus = true; - } - else { - if (bIsMe) - type.bPeerBroadcast = true; - else - type.bOtherBroadcast = true; - } - szChatId = msgFrom; - szAuthor = participant; - } - else { - debugLogA("invalid message type"); - return; - } - - CMStringA szSender = (type.bPrivateChat) ? szAuthor : szChatId; - bool bFromMe = (m_szJid == msgFrom); - if (!bFromMe && participant) - bFromMe = m_szJid == participant; - - auto *pKey = new proto::MessageKey(); - pKey->set_remotejid(szChatId); - pKey->set_id(msgId); - pKey->set_fromme(bFromMe); - if (participant) - pKey->set_participant(participant); - - proto::WebMessageInfo msg; - msg.set_allocated_key(pKey); - msg.set_messagetimestamp(_atoi64(node.getAttr("t"))); - msg.set_pushname(node.getAttr("notify")); - if (bFromMe) - msg.set_status(proto::WebMessageInfo_Status_SERVER_ACK); - - int iDecryptable = 0; - - for (auto &it: node.getChildren()) { - if (it->title == "verified_name") { - proto::VerifiedNameCertificate cert; - cert << it->content; + if (auto *pChild = node.getFirstChild()) { + if (pChild->title == "offline") { + debugLogA("Processed %d offline events", pChild->getAttrInt("count")); - proto::VerifiedNameCertificate::Details details; - details.ParseFromString(cert.details()); - - msg.set_verifiedbizname(details.verifiedname()); - continue; - } - - if (it->title != "enc" || it->content.length() == 0) - continue; - - SignalBuffer msgBody; - auto *pszType = it->getAttr("type"); - try { - if (!mir_strcmp(pszType, "pkmsg") || !mir_strcmp(pszType, "msg")) { - CMStringA szUser = (WAJid(szSender).isUser()) ? szSender : szAuthor; - msgBody = m_signalStore.decryptSignalProto(szUser, pszType, it->content); - } - else if (!mir_strcmp(pszType, "skmsg")) { - msgBody = m_signalStore.decryptGroupSignalProto(szSender, szAuthor, it->content); + // retrieve loaded prekeys count + if (!m_bUpdatedPrekeys) + WSSendNode(WANodeIq(IQ::GET, "encrypt") << XCHILD("count"), &WhatsAppProto::OnIqCountPrekeys); + + for (auto &it: m_arCollections) { + if (it->version == 0) { + m_impl.m_resyncApp.Stop(); + m_impl.m_resyncApp.Start(1000); + break; + } } - else throw "Invalid e2e type"; - - if (!msgBody) - throw "Invalid e2e message"; - - iDecryptable++; - - proto::Message encMsg; - encMsg.ParseFromArray(msgBody.data(), msgBody.len()); - if (encMsg.devicesentmessage().has_message()) - msg.set_allocated_message(new proto::Message(encMsg.devicesentmessage().message())); - else - msg.set_allocated_message(new proto::Message(encMsg)); - - if (encMsg.has_senderkeydistributionmessage()) - m_signalStore.processSenderKeyMessage(encMsg.senderkeydistributionmessage()); - - ProcessMessage(type, msg); - msg.clear_message(); - - // send receipt - const char *pszReceiptType = nullptr, *pszReceiptTo = participant; - if (!mir_strcmp(category, "peer")) - pszReceiptType = "peer_msg"; - else if (bFromMe) { - // message was sent by me from a different device - pszReceiptType = "sender"; - if (WAJid(szChatId).isUser()) - pszReceiptTo = szAuthor; - } - else if (!m_hServerConn) - pszReceiptType = "inactive"; - - SendReceipt(szChatId, pszReceiptTo, msgId, pszReceiptType); - } - catch (const char *) { - } - - if (!iDecryptable) { - debugLogA("Nothing to decrypt"); - return; } } } @@ -579,6 +429,7 @@ void WhatsAppProto::InitPersistentHandlers() m_arPersistent.insert(new WAPersistentHandler("iq", "set", "md", "pair-device", &WhatsAppProto::OnIqPairDevice)); m_arPersistent.insert(new WAPersistentHandler("iq", "set", "md", "pair-success", &WhatsAppProto::OnIqPairSuccess)); + m_arPersistent.insert(new WAPersistentHandler("notification", "devices", 0, 0, &WhatsAppProto::OnNotifyDevices)); m_arPersistent.insert(new WAPersistentHandler("notification", "encrypt", 0, 0, &WhatsAppProto::OnNotifyEncrypt)); m_arPersistent.insert(new WAPersistentHandler("notification", "account_sync", 0, 0, &WhatsAppProto::OnAccountSync)); m_arPersistent.insert(new WAPersistentHandler("notification", "server_sync", 0, 0, &WhatsAppProto::OnServerSync)); diff --git a/protocols/WhatsApp/src/message.cpp b/protocols/WhatsApp/src/message.cpp index 806fbf1198..1952e57fc4 100644 --- a/protocols/WhatsApp/src/message.cpp +++ b/protocols/WhatsApp/src/message.cpp @@ -7,6 +7,171 @@ Copyright © 2019-22 George Hazan #include "stdafx.h" +void WhatsAppProto::OnReceiveMessage(const WANode &node) +{ + auto *msgId = node.getAttr("id"); + auto *msgType = node.getAttr("type"); + auto *msgFrom = node.getAttr("from"); + auto *category = node.getAttr("category"); + auto *recipient = node.getAttr("recipient"); + auto *participant = node.getAttr("participant"); + + if (msgType == nullptr || msgFrom == nullptr || msgId == nullptr) { + debugLogA("bad message received: <%s> <%s> <%s>", msgType, msgFrom, msgId); + return; + } + + WAMSG type; + WAJid jid(msgFrom); + CMStringA szAuthor, szChatId; + + if (node.getAttr("offline")) + type.bOffline = true; + + // message from one user to another + if (jid.isUser()) { + if (recipient) { + if (m_szJid != msgFrom) { + debugLogA("strange message: with recipient, but not from me"); + return; + } + szChatId = recipient; + } + else szChatId = msgFrom; + + type.bPrivateChat = true; + szAuthor = msgFrom; + } + else if (jid.isGroup()) { + if (!participant) { + debugLogA("strange message: from group, but without participant"); + return; + } + + type.bGroupChat = true; + szAuthor = participant; + szChatId = msgFrom; + } + else if (jid.isBroadcast()) { + if (!participant) { + debugLogA("strange message: from group, but without participant"); + return; + } + + bool bIsMe = m_szJid == participant; + if (jid.isStatusBroadcast()) { + if (bIsMe) + type.bDirectStatus = true; + else + type.bOtherStatus = true; + } + else { + if (bIsMe) + type.bPeerBroadcast = true; + else + type.bOtherBroadcast = true; + } + szChatId = msgFrom; + szAuthor = participant; + } + else { + debugLogA("invalid message type"); + return; + } + + CMStringA szSender = (type.bPrivateChat) ? szAuthor : szChatId; + bool bFromMe = (m_szJid == msgFrom); + if (!bFromMe && participant) + bFromMe = m_szJid == participant; + + auto *pKey = new proto::MessageKey(); + pKey->set_remotejid(szChatId); + pKey->set_id(msgId); + pKey->set_fromme(bFromMe); + if (participant) + pKey->set_participant(participant); + + proto::WebMessageInfo msg; + msg.set_allocated_key(pKey); + msg.set_messagetimestamp(_atoi64(node.getAttr("t"))); + msg.set_pushname(node.getAttr("notify")); + if (bFromMe) + msg.set_status(proto::WebMessageInfo_Status_SERVER_ACK); + + int iDecryptable = 0; + + for (auto &it : node.getChildren()) { + if (it->title == "verified_name") { + proto::VerifiedNameCertificate cert; + cert << it->content; + + proto::VerifiedNameCertificate::Details details; + details.ParseFromString(cert.details()); + + msg.set_verifiedbizname(details.verifiedname()); + continue; + } + + if (it->title != "enc" || it->content.length() == 0) + continue; + + SignalBuffer msgBody; + auto *pszType = it->getAttr("type"); + try { + if (!mir_strcmp(pszType, "pkmsg") || !mir_strcmp(pszType, "msg")) { + CMStringA szUser = (WAJid(szSender).isUser()) ? szSender : szAuthor; + msgBody = m_signalStore.decryptSignalProto(szUser, pszType, it->content); + } + else if (!mir_strcmp(pszType, "skmsg")) { + msgBody = m_signalStore.decryptGroupSignalProto(szSender, szAuthor, it->content); + } + else throw "Invalid e2e type"; + + if (!msgBody) + throw "Invalid e2e message"; + + iDecryptable++; + + proto::Message encMsg; + encMsg.ParseFromArray(msgBody.data(), msgBody.len()); + if (encMsg.devicesentmessage().has_message()) + msg.set_allocated_message(new proto::Message(encMsg.devicesentmessage().message())); + else + msg.set_allocated_message(new proto::Message(encMsg)); + + if (encMsg.has_senderkeydistributionmessage()) + m_signalStore.processSenderKeyMessage(encMsg.senderkeydistributionmessage()); + + ProcessMessage(type, msg); + msg.clear_message(); + + // send receipt + const char *pszReceiptType = nullptr, *pszReceiptTo = participant; + if (!mir_strcmp(category, "peer")) + pszReceiptType = "peer_msg"; + else if (bFromMe) { + // message was sent by me from a different device + pszReceiptType = "sender"; + if (WAJid(szChatId).isUser()) + pszReceiptTo = szAuthor; + } + else if (!m_hServerConn) + pszReceiptType = "inactive"; + + SendReceipt(szChatId, pszReceiptTo, msgId, pszReceiptType); + } + catch (const char *) { + } + + if (!iDecryptable) { + debugLogA("Nothing to decrypt"); + return; + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + static const proto::Message& getBody(const proto::Message &message) { if (message.has_ephemeralmessage()) { diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h index 5814aa7538..a5b6a60f57 100644 --- a/protocols/WhatsApp/src/proto.h +++ b/protocols/WhatsApp/src/proto.h @@ -243,7 +243,7 @@ class WhatsAppProto : public PROTO<WhatsAppProto> } } m_impl; - bool m_bTerminated, m_bRespawn; + bool m_bTerminated, m_bRespawn, m_bUpdatedPrekeys; ptrW m_tszDefaultGroup; CMStringA m_szJid; @@ -346,6 +346,7 @@ class WhatsAppProto : public PROTO<WhatsAppProto> void OnIqPairSuccess(const WANode &node); void OnIqResult(const WANode &node); void OnIqServerSync(const WANode &node); + void OnNotifyDevices(const WANode &node); void OnNotifyEncrypt(const WANode &node); void OnReceiveInfo(const WANode &node); void OnReceiveMessage(const WANode &node); diff --git a/protocols/WhatsApp/src/server.cpp b/protocols/WhatsApp/src/server.cpp index f638f1a8b3..efe293c5b0 100644 --- a/protocols/WhatsApp/src/server.cpp +++ b/protocols/WhatsApp/src/server.cpp @@ -227,14 +227,10 @@ void WhatsAppProto::OnLoggedIn() ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, m_iDesiredStatus); m_iStatus = m_iDesiredStatus; + m_bUpdatedPrekeys = false; m_impl.m_keepAlive.Start(1000); - // retrieve loaded prekeys count - WSSendNode( - WANodeIq(IQ::GET, "encrypt") << XCHILD("count"), - &WhatsAppProto::OnIqCountPrekeys); - // retrieve initial info WANodeIq abt(IQ::GET, "abt"); abt.addChild("props")->addAttr("protocol", "1"); @@ -294,7 +290,7 @@ void WhatsAppProto::SendReceipt(const char *pszTo, const char *pszParticipant, c if (pszType) receipt << CHAR_PARAM("type", pszType); - WSSendNode(receipt, &WhatsAppProto::OnIqDoNothing); + WSSendNode(receipt); } void WhatsAppProto::SetServerStatus(int iStatus) |