From 37a61502be9d19eb89efd2c8c0cbe0debe968333 Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Wed, 28 Mar 2018 10:03:13 +0300 Subject: prootcols: jabber: xep-0198 - send ack on disconnect as suggested by xep - bugfixes (outgoing messages tracking still does not work properly) --- protocols/JabberG/src/jabber_proto.cpp | 2 + protocols/JabberG/src/jabber_strm_mgmt.cpp | 82 +++++++++++++++++------------- protocols/JabberG/src/jabber_strm_mgmt.h | 1 + protocols/JabberG/src/jabber_thread.cpp | 24 +++++++-- protocols/JabberG/src/stdafx.h | 1 + 5 files changed, 70 insertions(+), 40 deletions(-) mode change 100644 => 100755 protocols/JabberG/src/stdafx.h (limited to 'protocols') diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 84310548fe..f2c0e992d7 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -1134,6 +1134,8 @@ int __cdecl CJabberProto::SetStatus(int iNewStatus) if (iNewStatus == ID_STATUS_OFFLINE) { if (m_ThreadInfo) { + if(m_bEnableStreamMgmt) + m_StrmMgmt.SendAck(); m_ThreadInfo->send(""); m_ThreadInfo->shutdown(); RebuildInfoFrame(); diff --git a/protocols/JabberG/src/jabber_strm_mgmt.cpp b/protocols/JabberG/src/jabber_strm_mgmt.cpp index 293e4783ad..aff05bf828 100755 --- a/protocols/JabberG/src/jabber_strm_mgmt.cpp +++ b/protocols/JabberG/src/jabber_strm_mgmt.cpp @@ -54,46 +54,54 @@ void strm_mgmt::OnProcessSMa(HXML node) int size = m_nStrmMgmtLocalSCount - m_nStrmMgmtSrvHCount; if (size < 0) { - //TODO: this should never happen, indicate server side bug - //TODO: once our side implementation good enough abort strem in this case, noop for now + //TODO: this should never happen, indicates server side bug + //TODO: once our client side implementation good enough, abort stream in this case, noop for now } - else if (size > 0) + else if (size > 0 && !NodeCache.empty()) //TODO: NodeCache cannot be empty if size >0, it's a bug { - const size_t diff = NodeCache.size() - size; - if (diff) + if (size <= NodeCache.size()) //TODO: size should not be larger than NodeCache.size(), another bug { - size_t diff_tmp = diff; - for (auto i : NodeCache) + const size_t diff = NodeCache.size() - size; + if (diff) { - if (diff_tmp > 0) + size_t diff_tmp = diff; + for (auto i : NodeCache) { - xmlFree(i); + if (diff_tmp > 0) + { + xmlFree(i); + diff_tmp--; + } + } + diff_tmp = diff; + while (diff_tmp) + { + NodeCache.pop_front(); diff_tmp--; } } - diff_tmp = diff; - while (diff_tmp) - { - NodeCache.pop_front(); - diff_tmp--; - } } + std::list tmp_list = NodeCache; + NodeCache.clear(); + for (auto i : tmp_list) + { + proto->m_ThreadInfo->send_no_strm_mgmt(i); //freed by send ? + //xmlFree(i); + } + } + else + { for (auto i : NodeCache) - proto->m_ThreadInfo->send(i); + xmlFree(i); + NodeCache.clear(); } - NodeCache.clear(); } } void strm_mgmt::OnProcessSMr(HXML node) { if (!mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3")) - { - XmlNode enable_sm(L"a"); - XmlAddAttr(enable_sm, L"xmlns", L"urn:xmpp:sm:3"); - xmlAddAttrInt(enable_sm, L"h", m_nStrmMgmtLocalHCount); - proto->m_ThreadInfo->send(enable_sm); - } + SendAck(); } void strm_mgmt::OnProcessFailed(HXML node, ThreadData * /*info*/) //used failed instead of failure, notes: https://xmpp.org/extensions/xep-0198.html#errors @@ -129,16 +137,13 @@ void strm_mgmt::HandleOutgoingNode(HXML node) { if (!m_bStrmMgmtEnabled) return; - auto name = XmlGetName(node); - if (mir_wstrcmp(name, L"a") && mir_wstrcmp(name, L"r")) + m_nStrmMgmtLocalSCount++; + NodeCache.push_back(xmlCopyNode(node)); + if ((m_nStrmMgmtLocalSCount - m_nStrmMgmtSrvHCount) >= m_nStrmMgmtCacheSize) { - m_nStrmMgmtLocalSCount++; - if ((m_nStrmMgmtLocalSCount - m_nStrmMgmtSrvHCount) >= m_nStrmMgmtCacheSize) - { - XmlNode enable_sm(L"r"); - XmlAddAttr(enable_sm, L"xmlns", L"urn:xmpp:sm:3"); - proto->m_ThreadInfo->send(enable_sm); - } + XmlNode enable_sm(L"r"); + XmlAddAttr(enable_sm, L"xmlns", L"urn:xmpp:sm:3"); + proto->m_ThreadInfo->send_no_strm_mgmt(enable_sm); } } @@ -155,10 +160,7 @@ void strm_mgmt::OnDisconnect() void strm_mgmt::HandleIncommingNode(HXML node) { if (m_bStrmMgmtEnabled && mir_wstrcmp(XmlGetName(node), L"r") && mir_wstrcmp(XmlGetName(node), L"a")) //TODO: something better - { - NodeCache.push_back(xmlCopyNode(node)); m_nStrmMgmtLocalHCount++; - } else if (!mir_wstrcmp(XmlGetName(node), L"r")) OnProcessSMr(node); else if (!mir_wstrcmp(XmlGetName(node), L"a")) @@ -172,4 +174,14 @@ void strm_mgmt::EnableStrmMgmt() XmlAddAttr(enable_sm, L"resume", L"true"); //enable resumption (most useful part of this xep) proto->m_ThreadInfo->send(enable_sm); m_nStrmMgmtLocalSCount = 1; //TODO: this MUST be 0, i have bug somewhere. +} + +void strm_mgmt::SendAck() +{ + if (!m_bStrmMgmtEnabled) + return; + XmlNode enable_sm(L"a"); + XmlAddAttr(enable_sm, L"xmlns", L"urn:xmpp:sm:3"); + xmlAddAttrInt(enable_sm, L"h", m_nStrmMgmtLocalHCount); + proto->m_ThreadInfo->send_no_strm_mgmt(enable_sm); } \ No newline at end of file diff --git a/protocols/JabberG/src/jabber_strm_mgmt.h b/protocols/JabberG/src/jabber_strm_mgmt.h index 178727e2c0..2bb770df77 100755 --- a/protocols/JabberG/src/jabber_strm_mgmt.h +++ b/protocols/JabberG/src/jabber_strm_mgmt.h @@ -50,6 +50,7 @@ public: void CheckStreamFeatures(HXML node); void CheckState(); void OnDisconnect(); + void SendAck(); }; #endif //JABBER_STRM_MGMT_H \ No newline at end of file diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index aee0373064..d79a2d72e0 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -128,6 +128,8 @@ void CJabberProto::OnPingReply(HXML, CJabberIqInfo *pInfo) return; if (pInfo->GetIqType() == JABBER_IQ_TYPE_FAIL) { // disconnect because of timeout + if (m_bEnableStreamMgmt) + m_StrmMgmt.SendAck(); m_ThreadInfo->send(""); m_ThreadInfo->shutdown(); } @@ -820,6 +822,8 @@ void CJabberProto::OnProcessError(HXML node, ThreadData *info) if (!skipMsg) MsgPopup(0, buff, TranslateT("Jabber Error")); + if (m_bEnableStreamMgmt) //TODO: check if needed/work here + m_StrmMgmt.SendAck(); info->send(""); } @@ -2113,6 +2117,18 @@ int ThreadData::send(HXML node) while (HXML parent = xmlGetParent(node)) node = parent; + int result = send_no_strm_mgmt(node); + + if (proto->m_bEnableStreamMgmt) + proto->m_StrmMgmt.HandleOutgoingNode(node); //TODO: is this a correct place ?, looks like some nodes does not goes here... + + return result; +} + +// this function required for send , and more important, for resend stuck nodes by strm_mgmt (xep-0198) +int ThreadData::send_no_strm_mgmt(HXML node) +{ + if (proto->m_sendManager.HandleSendPermanent(node, this)) return 0; @@ -2132,12 +2148,10 @@ int ThreadData::send(HXML node) } *q = 0; - T2Utf utfStr(str); int result = send(utfStr, (int)mir_strlen(utfStr)); - xmlFree(str); - if (proto->m_bEnableStreamMgmt) - proto->m_StrmMgmt.HandleOutgoingNode(node); //TODO: is this a correct place ? + return result; -} + +} \ No newline at end of file diff --git a/protocols/JabberG/src/stdafx.h b/protocols/JabberG/src/stdafx.h old mode 100644 new mode 100755 index ca39578fe3..41e02d9b85 --- a/protocols/JabberG/src/stdafx.h +++ b/protocols/JabberG/src/stdafx.h @@ -403,6 +403,7 @@ struct ThreadData int recv(char* buf, size_t len); int send(char* buffer, int bufsize = -1); int send(HXML node); + int send_no_strm_mgmt(HXML node); int recvws(char* buffer, size_t bufsize, int flags); int sendws(char* buffer, size_t bufsize, int flags); -- cgit v1.2.3