From c13df8fa3e1f60b059cecf3f3d6c825b7e86ac16 Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Tue, 17 Apr 2018 03:26:20 +0300 Subject: protocols: jabber: xep-0198: - improoved logic - fixed resumption - added few temporary workarounds for broken counters --- protocols/JabberG/src/jabber_strm_mgmt.cpp | 50 +++++++++++++++++++++++++++--- protocols/JabberG/src/jabber_strm_mgmt.h | 1 + protocols/JabberG/src/jabber_thread.cpp | 35 +++++++++++---------- 3 files changed, 65 insertions(+), 21 deletions(-) (limited to 'protocols/JabberG/src') diff --git a/protocols/JabberG/src/jabber_strm_mgmt.cpp b/protocols/JabberG/src/jabber_strm_mgmt.cpp index 21c9bc4d41..1856997270 100755 --- a/protocols/JabberG/src/jabber_strm_mgmt.cpp +++ b/protocols/JabberG/src/jabber_strm_mgmt.cpp @@ -64,11 +64,19 @@ void strm_mgmt::OnProcessResumed(HXML node, ThreadData * /*info*/) if (!var) return; bSessionResumed = true; + m_bStrmMgmtEnabled = true; + m_bStrmMgmtPendingEnable = false; m_nStrmMgmtSrvHCount = _wtoi(var); int size = m_nStrmMgmtLocalSCount - m_nStrmMgmtSrvHCount; + + //FinishLoginProcess(info); + proto->OnLoggedIn(); + proto->ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)proto->m_iStatus, proto->m_iDesiredStatus); + if (size < 0) { proto->debugLogA("strm_mgmt: error: locally sent nodes count %d, server side received count %d", m_nStrmMgmtLocalSCount, m_nStrmMgmtSrvHCount); + m_nStrmMgmtLocalSCount = m_nStrmMgmtSrvHCount; //temporary workaround //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 } @@ -93,6 +101,7 @@ void strm_mgmt::OnProcessSMa(HXML node) if (size < 0) { proto->debugLogA("strm_mgmt: error: locally sent nodes count %d, server side received count %d", m_nStrmMgmtLocalSCount, m_nStrmMgmtSrvHCount); + m_nStrmMgmtLocalSCount = m_nStrmMgmtSrvHCount; //temporary workaround //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 } @@ -134,9 +143,11 @@ void strm_mgmt::ResendNodes(uint32_t size) } std::list tmp_list = NodeCache; NodeCache.clear(); + m_nStrmMgmtLocalSCount = m_nStrmMgmtSrvHCount; //we have handled missed nodes, set our counter to match server side value for (auto i : tmp_list) { - proto->m_ThreadInfo->send_no_strm_mgmt(i); //freed by send ? + proto->m_ThreadInfo->send(i); + //proto->m_ThreadInfo->send_no_strm_mgmt(i); //freed by send ? //xmlFree(i); } } @@ -147,15 +158,25 @@ void strm_mgmt::OnProcessSMr(HXML node) SendAck(); } -void strm_mgmt::OnProcessFailed(HXML node, ThreadData * /*info*/) //used failed instead of failure, notes: https://xmpp.org/extensions/xep-0198.html#errors +void strm_mgmt::OnProcessFailed(HXML node, ThreadData * info) //used failed instead of failure, notes: https://xmpp.org/extensions/xep-0198.html#errors { if (mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3")) return; proto->debugLogW(L"strm_mgmt: error: Failed to resume session %s", m_sStrmMgmtResumeId.c_str()); + m_bStrmMgmtEnabled = false; bSessionResumed = false; m_sStrmMgmtResumeId.clear(); - EnableStrmMgmt(); //resume failed, try to enable strm_mgmt instead + { + HXML subnode = XmlGetChild(node, L"item-not-found"); + if (subnode) + { + m_bStrmMgmtPendingEnable = true; + FinishLoginProcess(info); + } + else + EnableStrmMgmt(); //resume failed, try to enable strm_mgmt instead + } } void strm_mgmt::CheckStreamFeatures(HXML node) @@ -257,4 +278,25 @@ bool strm_mgmt::IsSessionResumed() bool strm_mgmt::IsResumeIdPresent() { return !m_sStrmMgmtResumeId.empty(); -} \ No newline at end of file +} + +void strm_mgmt::FinishLoginProcess(ThreadData *info) +{ + + if (info->auth) + { //We are already logged-in + info->send( + XmlNodeIq(proto->AddIQ(&CJabberProto::OnIqResultBind, JABBER_IQ_TYPE_SET)) + << XCHILDNS(L"bind", L"urn:ietf:params:xml:ns:xmpp-bind") + << XCHILD(L"resource", info->resource)); + + if (proto->m_AuthMechs.isSessionAvailable) + info->bIsSessionAvailable = TRUE; + + return; + } + + //mechanisms not available and we are not logged in + proto->PerformIqAuth(info); + +} diff --git a/protocols/JabberG/src/jabber_strm_mgmt.h b/protocols/JabberG/src/jabber_strm_mgmt.h index 03d3cd42e0..78d6ce3269 100755 --- a/protocols/JabberG/src/jabber_strm_mgmt.h +++ b/protocols/JabberG/src/jabber_strm_mgmt.h @@ -32,6 +32,7 @@ class strm_mgmt void OnProcessSMa(HXML node); void OnProcessSMr(HXML node); void ResendNodes(uint32_t count); + void FinishLoginProcess(ThreadData *info); CJabberProto *proto; diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index c032af1727..653e8af1bb 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -760,27 +760,26 @@ void CJabberProto::OnProcessFeatures(HXML node, ThreadData *info) return; } - if (m_bEnableStreamMgmt) //resume should be done here + if (m_bEnableStreamMgmt && m_StrmMgmt.IsResumeIdPresent()) //resume should be done here + m_StrmMgmt.CheckState(); + else { - if (m_StrmMgmt.IsResumeIdPresent()) - m_StrmMgmt.CheckState(); - } - - // mechanisms are not defined. - if (info->auth) { //We are already logged-in - info->send( - XmlNodeIq(AddIQ(&CJabberProto::OnIqResultBind, JABBER_IQ_TYPE_SET)) + // mechanisms are not defined. + if (info->auth) { //We are already logged-in + info->send( + XmlNodeIq(AddIQ(&CJabberProto::OnIqResultBind, JABBER_IQ_TYPE_SET)) << XCHILDNS(L"bind", L"urn:ietf:params:xml:ns:xmpp-bind") << XCHILD(L"resource", info->resource)); - if (m_AuthMechs.isSessionAvailable) - info->bIsSessionAvailable = TRUE; + if (m_AuthMechs.isSessionAvailable) + info->bIsSessionAvailable = TRUE; - return; - } + return; + } - //mechanisms not available and we are not logged in - PerformIqAuth(info); + //mechanisms not available and we are not logged in + PerformIqAuth(info); + } } void CJabberProto::OnProcessFailure(HXML node, ThreadData *info) @@ -2132,11 +2131,13 @@ 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... + + int result = send_no_strm_mgmt(node); + + return result; } -- cgit v1.2.3