summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp/src/iq.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/WhatsApp/src/iq.cpp')
-rw-r--r--protocols/WhatsApp/src/iq.cpp256
1 files changed, 146 insertions, 110 deletions
diff --git a/protocols/WhatsApp/src/iq.cpp b/protocols/WhatsApp/src/iq.cpp
index 063a71264c..8abf959895 100644
--- a/protocols/WhatsApp/src/iq.cpp
+++ b/protocols/WhatsApp/src/iq.cpp
@@ -76,129 +76,27 @@ void WhatsAppProto::UploadMorePrekeys()
/////////////////////////////////////////////////////////////////////////////////////////
-void WhatsAppProto::OnIqDoNothing(const WANode &)
+void WhatsAppProto::OnIqDoNothing(const WANode&)
{
}
/////////////////////////////////////////////////////////////////////////////////////////
-void WhatsAppProto::OnNotifyDevices(const WANode &node)
-{
- if (!mir_strcmp(node.getAttr("jid"), m_szJid))
- debugLogA("received list of my own devices");
- SendAck(node);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void WhatsAppProto::OnNotifyEncrypt(const WANode &node)
-{
- if (!mir_strcmp(node.getAttr("from"), S_WHATSAPP_NET))
- OnIqCountPrekeys(node);
- SendAck(node);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void WhatsAppProto::OnReceiveInfo(const WANode &node)
+void WhatsAppProto::OnIqGetUsync(const WANode &node)
{
- if (auto *pChild = node.getFirstChild()) {
- if (pChild->title == "offline") {
- debugLogA("Processed %d offline events", pChild->getAttrInt("count"));
-
- // 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;
- }
- }
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void WhatsAppProto::ProcessReceipt(MCONTACT hContact, const char *msgId, bool bRead)
-{
- MEVENT hEvent = db_event_getById(m_szModuleName, msgId);
- if (hEvent == 0)
- return;
-
- if (g_plugin.bHasMessageState)
- CallService(MS_MESSAGESTATE_UPDATE, hContact, bRead ? MRD_TYPE_READ : MRD_TYPE_DELIVERED);
-
- if (bRead)
- db_event_markRead(hContact, hEvent);
-}
-
-void WhatsAppProto::OnReceiveReceipt(const WANode &node)
-{
- if (auto *pUser = FindUser(node.getAttr("from"))) {
- bool bRead = mir_strcmp(node.getAttr("type"), "read") == 0;
- ProcessReceipt(pUser->hContact, node.getAttr("id"), bRead);
+ m_arDevices.destroy();
- if (auto *pList = node.getChild("list"))
+ if (auto *nUser = node.getChild("usync")->getChild("list")->getChild("user")) {
+ auto *pszJid = nUser->getAttr("jid");
+ if (auto *pList = nUser->getChild("devices")->getChild("device-list"))
for (auto &it : pList->getChildren())
- if (it->title == "item")
- ProcessReceipt(pUser->hContact, it->getAttr("id"), bRead);
- }
-
- SendAck(node);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void WhatsAppProto::OnStreamError(const WANode &node)
-{
- m_bTerminated = true;
-
- if (auto *pszCode = node.getAttr("code")) {
- switch (atoi(pszCode)) {
- case 401:
- debugLogA("Connection logged out from another device, exiting");
- break;
-
- case 408:
- debugLogA("Connection lost, exiting");
- break;
-
- case 411:
- debugLogA("Conflict between two devices, exiting");
- break;
-
- case 428:
- debugLogA("Connection forcibly closed by the server, exiting");
- break;
-
- case 440:
- debugLogA("Connection replaced from another device, exiting");
- break;
-
- case 515:
- debugLogA("Server required to restart immediately, leaving thread");
- m_bRespawn = true;
- break;
- }
+ if (it->title == "device")
+ m_arDevices.insert(new WADevice(pszJid, it->getAttrInt("id")));
}
}
/////////////////////////////////////////////////////////////////////////////////////////
-void WhatsAppProto::OnIqResult(const WANode &node)
-{
- if (auto *pszId = node.getAttr("id"))
- for (auto &it: m_arPacketQueue)
- if (it->szPacketId == pszId)
- (this->*it->pHandler)(node);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
void WhatsAppProto::OnIqPairDevice(const WANode &node)
{
WSSendNode(WANodeIq(IQ::RESULT) << CHAR_PARAM("id", node.getAttr("id")));
@@ -325,6 +223,41 @@ void WhatsAppProto::OnIqPairSuccess(const WANode &node)
/////////////////////////////////////////////////////////////////////////////////////////
+void WhatsAppProto::OnIqResult(const WANode &node)
+{
+ if (auto *pszId = node.getAttr("id"))
+ for (auto &it : m_arPacketQueue)
+ if (it->szPacketId == pszId)
+ (this->*it->pHandler)(node);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void WhatsAppProto::OnNotifyAny(const WANode &node)
+{
+ SendAck(node);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void WhatsAppProto::OnNotifyDevices(const WANode &node)
+{
+ if (!mir_strcmp(node.getAttr("jid"), m_szJid))
+ debugLogA("received list of my own devices");
+ SendAck(node);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void WhatsAppProto::OnNotifyEncrypt(const WANode &node)
+{
+ if (!mir_strcmp(node.getAttr("from"), S_WHATSAPP_NET))
+ OnIqCountPrekeys(node);
+ SendAck(node);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
void WhatsAppProto::OnProcessHandshake(const void *pData, int cbLen)
{
proto::HandshakeMessage msg;
@@ -449,6 +382,108 @@ LBL_Error:
/////////////////////////////////////////////////////////////////////////////////////////
+void WhatsAppProto::OnReceiveInfo(const WANode &node)
+{
+ if (auto *pChild = node.getFirstChild()) {
+ if (pChild->title == "offline") {
+ debugLogA("Processed %d offline events", pChild->getAttrInt("count"));
+
+ // retrieve loaded prekeys count
+ if (!m_bUpdatedPrekeys)
+ WSSendNode(WANodeIq(IQ::GET, "encrypt") << XCHILD("count"), &WhatsAppProto::OnIqCountPrekeys);
+
+ if (m_arDevices.getCount() == 0) {
+ WANodeIq iq(IQ::GET, "usync");
+
+ auto *pNode1 = iq.addChild("usync");
+ *pNode1 << CHAR_PARAM("sid", GenerateMessageId()) << CHAR_PARAM("mode", "query") << CHAR_PARAM("last", "true")
+ << CHAR_PARAM("index", "0") << CHAR_PARAM("context", "message");
+
+ pNode1->addChild("query")->addChild("devices")->addAttr("version", "2");
+ pNode1->addChild("list")->addChild("user")->addAttr("jid", m_szJid);
+
+ WSSendNode(iq, &WhatsAppProto::OnIqGetUsync);
+ }
+
+ for (auto &it : m_arCollections) {
+ if (it->version == 0) {
+ m_impl.m_resyncApp.Stop();
+ m_impl.m_resyncApp.Start(1000);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void WhatsAppProto::ProcessReceipt(MCONTACT hContact, const char *msgId, bool bRead)
+{
+ MEVENT hEvent = db_event_getById(m_szModuleName, msgId);
+ if (hEvent == 0)
+ return;
+
+ if (g_plugin.bHasMessageState)
+ CallService(MS_MESSAGESTATE_UPDATE, hContact, bRead ? MRD_TYPE_READ : MRD_TYPE_DELIVERED);
+
+ if (bRead)
+ db_event_markRead(hContact, hEvent);
+}
+
+void WhatsAppProto::OnReceiveReceipt(const WANode &node)
+{
+ if (auto *pUser = FindUser(node.getAttr("from"))) {
+ bool bRead = mir_strcmp(node.getAttr("type"), "read") == 0;
+ ProcessReceipt(pUser->hContact, node.getAttr("id"), bRead);
+
+ if (auto *pList = node.getChild("list"))
+ for (auto &it : pList->getChildren())
+ if (it->title == "item")
+ ProcessReceipt(pUser->hContact, it->getAttr("id"), bRead);
+ }
+
+ SendAck(node);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void WhatsAppProto::OnStreamError(const WANode &node)
+{
+ m_bTerminated = true;
+
+ if (auto *pszCode = node.getAttr("code")) {
+ switch (atoi(pszCode)) {
+ case 401:
+ debugLogA("Connection logged out from another device, exiting");
+ break;
+
+ case 408:
+ debugLogA("Connection lost, exiting");
+ break;
+
+ case 411:
+ debugLogA("Conflict between two devices, exiting");
+ break;
+
+ case 428:
+ debugLogA("Connection forcibly closed by the server, exiting");
+ break;
+
+ case 440:
+ debugLogA("Connection replaced from another device, exiting");
+ break;
+
+ case 515:
+ debugLogA("Server required to restart immediately, leaving thread");
+ m_bRespawn = true;
+ break;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
void WhatsAppProto::OnSuccess(const WANode &)
{
OnLoggedIn();
@@ -467,6 +502,7 @@ void WhatsAppProto::InitPersistentHandlers()
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));
+ m_arPersistent.insert(new WAPersistentHandler("notification", 0, 0, 0, &WhatsAppProto::OnNotifyAny));
m_arPersistent.insert(new WAPersistentHandler("ib", 0, 0, 0, &WhatsAppProto::OnReceiveInfo));
m_arPersistent.insert(new WAPersistentHandler("message", 0, 0, 0, &WhatsAppProto::OnReceiveMessage));