diff options
author | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2018-03-28 08:21:09 +0300 |
---|---|---|
committer | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2018-03-28 08:21:09 +0300 |
commit | 5e65ecbf7c7e008ac23adc0f29bc000f7fd27019 (patch) | |
tree | 480f2c5510c8aef3b5a25325378f3035ea0099a4 /protocols/JabberG/src | |
parent | 351c13a90dd7d95e15e6b15632ec5c255398abd3 (diff) |
protocols: jabber: xep-0198
- moved implementation to separated units (refactoring)
- first part (without resumption) should work now (still have some bugs), feel free to test
Diffstat (limited to 'protocols/JabberG/src')
-rwxr-xr-x | protocols/JabberG/src/jabber_iqid.cpp | 6 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_opt.cpp | 2 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_proto.cpp | 13 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 8 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_strm_mgmt.cpp | 175 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_strm_mgmt.h | 55 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 95 |
7 files changed, 247 insertions, 107 deletions
diff --git a/protocols/JabberG/src/jabber_iqid.cpp b/protocols/JabberG/src/jabber_iqid.cpp index 83febdd7ed..c2d2d1313e 100755 --- a/protocols/JabberG/src/jabber_iqid.cpp +++ b/protocols/JabberG/src/jabber_iqid.cpp @@ -214,11 +214,7 @@ void CJabberProto::OnLoggedIn() setString("LastLoggedServer", m_ThreadInfo->conn.server);
m_pepServices.ResetPublishAll();
if (m_bEnableStreamMgmt)
- {
- if (m_bStrmMgmtPendingEnable && !m_bStrmMgmtEnabled)
- EnableStrmMgmt();
- }
-
+ m_StrmMgmt.CheckState();
}
void CJabberProto::OnIqResultGetAuth(HXML iqNode, CJabberIqInfo*)
diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp index 32a44d95f9..c63430d79a 100755 --- a/protocols/JabberG/src/jabber_opt.cpp +++ b/protocols/JabberG/src/jabber_opt.cpp @@ -795,7 +795,7 @@ public: m_otvOptions.AddOption(LPGENW("Messaging") L"/" LPGENW("Automatically save received notes"), m_proto->m_bAutosaveNotes);
m_otvOptions.AddOption(LPGENW("Messaging") L"/" LPGENW("Enable server-side history (XEP-0136)"), m_proto->m_bEnableMsgArchive);
m_otvOptions.AddOption(LPGENW("Messaging") L"/" LPGENW("Receive conversations from other devices (XEP-0280)"), m_proto->m_bEnableCarbons);
- m_otvOptions.AddOption(LPGENW("Messaging") L"/" LPGENW("Use Stream Management (XEP-0198) if possible (PLACEHOLDER OPTION)"), m_proto->m_bEnableStreamMgmt);
+ m_otvOptions.AddOption(LPGENW("Messaging") L"/" LPGENW("Use Stream Management (XEP-0198) if possible (WIP! no resumption yet)"), m_proto->m_bEnableStreamMgmt);
m_otvOptions.AddOption(LPGENW("Server options") L"/" LPGENW("Disable SASL authentication (for old servers)"), m_proto->m_bDisable3920auth);
m_otvOptions.AddOption(LPGENW("Server options") L"/" LPGENW("Enable stream compression (if possible)"), m_proto->m_bEnableZlib);
diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 6a125f7ffc..84310548fe 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -71,10 +71,7 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) : m_hPrivacyMenuItems(10),
m_lstJabberFeatCapPairsDynamic(2),
m_uEnabledFeatCapsDynamic(0),
- m_bStrmMgmtPendingEnable(false),
- m_bStrmMgmtEnabled(false),
- m_bStrmMgmtResumeSupported(false),
- m_sStrmMgmtResumeId(nullptr),
+ m_StrmMgmt(this),
m_bBsDirect(this, "BsDirect", TRUE),
m_bAllowVersionRequests(this, "m_bAllowVersionRequests", TRUE),
@@ -258,8 +255,6 @@ CJabberProto::~CJabberProto() delete it;
}
- if (m_sStrmMgmtResumeId)
- mir_free(m_sStrmMgmtResumeId);
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -1349,9 +1344,3 @@ int __cdecl CJabberProto::OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPARA }
return 1;
}
-
-
-void CJabberProto::m_nStrmMgmtLocalSCount_incr()
-{
- m_nStrmMgmtLocalSCount++;
-}
\ No newline at end of file diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index 328192a811..729ca52efe 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "jabber_presence_manager.h"
#include "jabber_send_manager.h"
#include "jabber_omemo.h"
+#include "jabber_strm_mgmt.h"
struct CJabberProto;
@@ -285,9 +286,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface int m_nIqIdRegSetReg;
//xep-0198 related vars
- uint32_t m_nStrmMgmtSrvHCount, m_nStrmMgmtLocalHCount, m_nStrmMgmtLocalSCount, m_nStrmMgmtResumeMaxSeconds;
- bool m_bStrmMgmtPendingEnable, m_bStrmMgmtEnabled, m_bStrmMgmtResumeSupported;
- wchar_t *m_sStrmMgmtResumeId;
+ strm_mgmt m_StrmMgmt;
int m_nSDBrowseMode;
DWORD m_dwSDLastRefresh;
@@ -805,7 +804,6 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface bool ProcessCaptcha(HXML node, HXML parentNode, ThreadData *info);
void EnableCarbons(bool bEnable);
- void EnableStrmMgmt();
//---- jabber_util.c -----------------------------------------------------------------
pResourceStatus ResourceInfoFromJID(const wchar_t *jid);
@@ -931,8 +929,6 @@ public: HNETLIBUSER STDMETHODCALLTYPE GetHandle(); // Returns connection handle
- void m_nStrmMgmtLocalSCount_incr();
-
private:
JabberFeatCapPairDynamic *FindFeature(const wchar_t *szFeature);
};
diff --git a/protocols/JabberG/src/jabber_strm_mgmt.cpp b/protocols/JabberG/src/jabber_strm_mgmt.cpp new file mode 100755 index 0000000000..293e4783ad --- /dev/null +++ b/protocols/JabberG/src/jabber_strm_mgmt.cpp @@ -0,0 +1,175 @@ +/*
+
+Jabber Protocol Plugin for Miranda NG
+
+Copyright (c) 2018 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "stdafx.h"
+#include "jabber_strm_mgmt.h"
+
+strm_mgmt::strm_mgmt(CJabberProto *_proto) : proto(_proto), m_bStrmMgmtPendingEnable(false),
+m_bStrmMgmtEnabled(false),
+m_bStrmMgmtResumeSupported(false)
+{
+
+}
+
+void strm_mgmt::OnProcessEnabled(HXML node, ThreadData * /*info*/)
+{
+ m_bStrmMgmtEnabled = true;
+ auto val = XmlGetAttrValue(node, L"max");
+ m_nStrmMgmtResumeMaxSeconds = _wtoi(val);
+ val = XmlGetAttrValue(node, L"resume");
+ if (mir_wstrcmp(val, L"true") || mir_wstrcmp(val, L"1"))
+ m_bStrmMgmtResumeSupported = true;
+
+ m_sStrmMgmtResumeId = XmlGetAttrValue(node, L"id");
+ m_nStrmMgmtLocalHCount = 0;
+ m_nStrmMgmtSrvHCount = 0;
+}
+
+void strm_mgmt::OnProcessSMa(HXML node)
+{
+ if (!mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3"))
+ {
+ auto val = XmlGetAttrValue(node, L"h");
+ uint32_t iVal = _wtoi(val);
+ m_nStrmMgmtSrvHCount = iVal;
+ 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
+ }
+ else if (size > 0)
+ {
+ const size_t diff = NodeCache.size() - size;
+ if (diff)
+ {
+ size_t diff_tmp = diff;
+ for (auto i : NodeCache)
+ {
+ if (diff_tmp > 0)
+ {
+ xmlFree(i);
+ diff_tmp--;
+ }
+ }
+ diff_tmp = diff;
+ while (diff_tmp)
+ {
+ NodeCache.pop_front();
+ diff_tmp--;
+ }
+ }
+ for (auto i : NodeCache)
+ proto->m_ThreadInfo->send(i);
+ }
+ 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);
+ }
+}
+
+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"))
+ {
+ //TODO: handle failure
+ }
+}
+
+void strm_mgmt::CheckStreamFeatures(HXML node)
+{
+ if (!mir_wstrcmp(XmlGetName(node), L"sm"))
+ {
+ if (!mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3")) //we work only with version 3 or higher of sm
+ {
+ if (!(proto->m_bJabberOnline))
+ m_bStrmMgmtPendingEnable = true;
+ else
+ EnableStrmMgmt();
+ }
+ }
+}
+
+void strm_mgmt::CheckState()
+{
+ if (m_bStrmMgmtPendingEnable)
+ EnableStrmMgmt();
+ //TODO: resume stream from here ?
+}
+
+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++;
+ 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);
+ }
+ }
+}
+
+void strm_mgmt::OnDisconnect()
+{
+ //TODO: following should be redone once resumption implemented
+ //reset state of stream management
+ m_bStrmMgmtEnabled = false;
+ m_bStrmMgmtPendingEnable = false;
+ //reset stream management h counters
+ m_nStrmMgmtLocalHCount = m_nStrmMgmtLocalSCount = m_nStrmMgmtSrvHCount = 0;
+}
+
+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"))
+ OnProcessSMa(node);
+}
+
+void strm_mgmt::EnableStrmMgmt()
+{
+ XmlNode enable_sm(L"enable");
+ XmlAddAttr(enable_sm, L"xmlns", L"urn:xmpp:sm:3");
+ 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.
+}
\ No newline at end of file diff --git a/protocols/JabberG/src/jabber_strm_mgmt.h b/protocols/JabberG/src/jabber_strm_mgmt.h new file mode 100755 index 0000000000..178727e2c0 --- /dev/null +++ b/protocols/JabberG/src/jabber_strm_mgmt.h @@ -0,0 +1,55 @@ +/*
+
+Jabber Protocol Plugin for Miranda NG
+
+Copyright (c) 2018 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef JABBER_STRM_MGMT_H
+#define JABBER_STRM_MGMT_H
+
+#include <list>
+
+struct CJabberProto;
+
+class strm_mgmt
+{
+ void OnProcessSMa(HXML node);
+ void OnProcessSMr(HXML node);
+
+
+ CJabberProto *proto;
+ uint32_t m_nStrmMgmtSrvHCount, m_nStrmMgmtLocalHCount, m_nStrmMgmtLocalSCount, m_nStrmMgmtResumeMaxSeconds;
+ const uint32_t m_nStrmMgmtCacheSize = 10;
+ bool m_bStrmMgmtPendingEnable, m_bStrmMgmtEnabled, m_bStrmMgmtResumeSupported;
+ std::wstring m_sStrmMgmtResumeId;
+ std::list<HXML> NodeCache;
+
+public:
+ strm_mgmt(CJabberProto *proto);
+ void EnableStrmMgmt();
+ void HandleOutgoingNode(HXML node);
+ void HandleIncommingNode(HXML node);
+ void OnProcessEnabled(HXML node, ThreadData *info);
+ void OnProcessFailed(HXML node, ThreadData * info);
+ void CheckStreamFeatures(HXML node);
+ void CheckState();
+ void OnDisconnect();
+};
+
+#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 e75d3ec81f..aee0373064 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -519,12 +519,8 @@ recvRest: m_iDesiredStatus = m_iStatus = ID_STATUS_OFFLINE;
ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
- //TODO: following should be redone once resumption implemented
- //reset state of stream management
- m_bStrmMgmtEnabled = false;
- m_bStrmMgmtPendingEnable = false;
- //reset stream management h counters
- m_nStrmMgmtLocalHCount = m_nStrmMgmtLocalSCount = m_nStrmMgmtSrvHCount = 0;
+
+ m_StrmMgmt.OnDisconnect();
// Set all contacts to offline
debugLogA("1");
@@ -744,15 +740,7 @@ void CJabberProto::OnProcessFeatures(HXML node, ThreadData *info) else if (!mir_wstrcmp(XmlGetName(n), L"auth")) m_AuthMechs.isAuthAvailable = true;
else if (!mir_wstrcmp(XmlGetName(n), L"session")) m_AuthMechs.isSessionAvailable = true;
else if (m_bEnableStreamMgmt && !mir_wstrcmp(XmlGetName(n), L"sm"))
- {
- if (!mir_wstrcmp(XmlGetAttrValue(n, L"xmlns"), L"urn:xmpp:sm:3")) //we work only with version 3 or higher of sm
- {
- if (!m_bJabberOnline)
- m_bStrmMgmtPendingEnable = true;
- else
- EnableStrmMgmt();
- }
- }
+ m_StrmMgmt.CheckStreamFeatures(n);
}
if (areMechanismsDefined) {
@@ -790,58 +778,18 @@ void CJabberProto::OnProcessFailure(HXML node, ThreadData *info) }
}
-void CJabberProto::OnProcessFailed(HXML node, ThreadData * /*info*/) //used failed instead of failure, notes: https://xmpp.org/extensions/xep-0198.html#errors
+void CJabberProto::OnProcessFailed(HXML node, ThreadData *info) //used failed instead of failure, notes: https://xmpp.org/extensions/xep-0198.html#errors
{
- if (m_bEnableStreamMgmt && !mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3"))
- {
- //TODO: handle failure
- }
+ m_StrmMgmt.OnProcessFailed(node, info);
}
-void CJabberProto::OnProcessEnabled(HXML node, ThreadData * /*info*/)
-{
- if (m_bEnableStreamMgmt && !mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3"))
- {
- m_bStrmMgmtEnabled = true;
- auto val = XmlGetAttrValue(node, L"max");
- m_nStrmMgmtResumeMaxSeconds = _wtoi(val);
- val = XmlGetAttrValue(node, L"resume");
- if (mir_wstrcmp(val, L"true") || mir_wstrcmp(val, L"1"))
- m_bStrmMgmtResumeSupported = true;
-
- if (m_sStrmMgmtResumeId)
- mir_free(m_sStrmMgmtResumeId);
- m_sStrmMgmtResumeId = mir_wstrdup(XmlGetAttrValue(node, L"id"));
- m_nStrmMgmtLocalHCount = 0;
- m_nStrmMgmtSrvHCount = 0; //?
- m_nStrmMgmtLocalSCount = 0;
- }
-}
-void CJabberProto::OnProcessSMa(HXML node, ThreadData * /*info*/)
+void CJabberProto::OnProcessEnabled(HXML node, ThreadData * info)
{
- if (!mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3"))
- {
- auto val = XmlGetAttrValue(node, L"h");
- uint32_t iVal = _wtoi(val);
- m_nStrmMgmtSrvHCount = iVal;
- if ((m_nStrmMgmtLocalSCount - m_nStrmMgmtSrvHCount) > 0)
- {
- //TODO: server have not handled some of sent nodes, handle situation
- }
- }
+ if (m_bEnableStreamMgmt && !mir_wstrcmp(XmlGetAttrValue(node, L"xmlns"), L"urn:xmpp:sm:3"))
+ m_StrmMgmt.OnProcessEnabled(node, info);
}
-void CJabberProto::OnProcessSMr(HXML node, ThreadData * /*info*/)
-{
- 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);
- m_ThreadInfo->send(enable_sm);
- }
-}
void CJabberProto::OnProcessError(HXML node, ThreadData *info)
{
@@ -919,8 +867,8 @@ void CJabberProto::OnProcessProtocol(HXML node, ThreadData *info) {
OnConsoleProcessXml(node, JCPF_IN);
- if (m_bEnableStreamMgmt && m_bStrmMgmtEnabled && mir_wstrcmp(XmlGetName(node), L"r") && mir_wstrcmp(XmlGetName(node), L"a")) //TODO: something better
- m_nStrmMgmtLocalHCount++;
+ if (m_bEnableStreamMgmt)
+ m_StrmMgmt.HandleIncommingNode(node);
if (!mir_wstrcmp(XmlGetName(node), L"proceed"))
OnProcessProceed(node, info);
else if (!mir_wstrcmp(XmlGetName(node), L"compressed"))
@@ -948,13 +896,6 @@ void CJabberProto::OnProcessProtocol(HXML node, ThreadData *info) OnProcessFailed(node, info);
else if (!mir_wstrcmp(XmlGetName(node), L"enabled"))
OnProcessEnabled(node, info);
- else if (m_bEnableStreamMgmt)
- {
- if (!mir_wstrcmp(XmlGetName(node), L"r"))
- OnProcessSMr(node, info);
- else if (!mir_wstrcmp(XmlGetName(node), L"a"))
- OnProcessSMa(node, info);
- }
else
debugLogA("Invalid top-level tag (only <message/> <presence/> and <iq/> allowed)");
}
@@ -2076,14 +2017,6 @@ void CJabberProto::EnableCarbons(bool bEnable) << XCHILDNS((bEnable) ? L"enable" : L"disable", JABBER_FEAT_CARBONS));
}
-void CJabberProto::EnableStrmMgmt()
-{
- XmlNode enable_sm(L"enable");
- XmlAddAttr(enable_sm, L"xmlns", L"urn:xmpp:sm:3");
- XmlAddAttr(enable_sm, L"resume", L"true"); //enable resumption (most useful part of this xep)
- m_ThreadInfo->send(enable_sm);
-}
-
/////////////////////////////////////////////////////////////////////////////////////////
// ThreadData constructor & destructor
@@ -2204,11 +2137,7 @@ int ThreadData::send(HXML node) int result = send(utfStr, (int)mir_strlen(utfStr));
xmlFree(str);
- if (proto->m_bEnableStreamMgmt && proto->m_bStrmMgmtEnabled)
- {
- auto name = XmlGetName(node);
- if(mir_wstrcmp(name, L"a") && mir_wstrcmp(name, L"r"))
- proto->m_nStrmMgmtLocalSCount_incr();
- }
+ if (proto->m_bEnableStreamMgmt)
+ proto->m_StrmMgmt.HandleOutgoingNode(node); //TODO: is this a correct place ?
return result;
}
|