summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-01-06 23:14:03 +0200
committerGeorge Hazan <ghazan@miranda.im>2019-01-06 23:14:03 +0200
commitb156c043fbf64ff4451c5e59c4724c6ff5182909 (patch)
treed091a5efd5b17c3549b164f0bafcfde8c7164b41 /protocols
parent80ccccc6c8889ef287e78e0cf31a268ec2a39942 (diff)
ICQ10:
- fixes #1693 (Miranda doesn't mark read messages as read) - fixes #1728 (massive socket leak)
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Icq10/src/main.cpp5
-rw-r--r--protocols/Icq10/src/proto.cpp53
-rw-r--r--protocols/Icq10/src/proto.h7
-rw-r--r--protocols/Icq10/src/server.cpp31
-rw-r--r--protocols/Icq10/src/stdafx.h2
5 files changed, 81 insertions, 17 deletions
diff --git a/protocols/Icq10/src/main.cpp b/protocols/Icq10/src/main.cpp
index 3a5267f444..0f1888952d 100644
--- a/protocols/Icq10/src/main.cpp
+++ b/protocols/Icq10/src/main.cpp
@@ -22,6 +22,8 @@
bool g_bPopupService;
+HWND g_hwndHeartbeat;
+
/////////////////////////////////////////////////////////////////////////////////////////
static PLUGININFOEX pluginInfoEx = {
@@ -60,6 +62,8 @@ int ModuleLoad(WPARAM, LPARAM)
int CMPlugin::Load()
{
+ g_hwndHeartbeat = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
+
HookEvent(ME_SYSTEM_MODULELOAD, ModuleLoad);
HookEvent(ME_SYSTEM_MODULEUNLOAD, ModuleLoad);
ModuleLoad(0, 0);
@@ -68,5 +72,6 @@ int CMPlugin::Load()
int CMPlugin::Unload()
{
+ DestroyWindow(g_hwndHeartbeat);
return 0;
}
diff --git a/protocols/Icq10/src/proto.cpp b/protocols/Icq10/src/proto.cpp
index 78d1961d46..21573a9595 100644
--- a/protocols/Icq10/src/proto.cpp
+++ b/protocols/Icq10/src/proto.cpp
@@ -38,6 +38,7 @@ CIcqProto::CIcqProto(const char* aProtoName, const wchar_t* aUserName) :
m_arHttpQueue(10),
m_arOwnIds(1),
m_arCache(20, NumericKeySortT),
+ arMarkReadQueue(10, NumericKeySortT),
m_evRequestsQueue(CreateEvent(nullptr, FALSE, FALSE, nullptr)),
m_dwUin(this, DB_KEY_UIN, 0),
m_szPassword(this, "Password")
@@ -51,6 +52,7 @@ CIcqProto::CIcqProto(const char* aProtoName, const wchar_t* aUserName) :
// events
HookProtoEvent(ME_OPT_INITIALISE, &CIcqProto::OnOptionsInit);
+ HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CIcqProto::OnDbEventRead);
// netlib handle
CMStringW descr(FORMAT, TranslateT("%s server connection"), m_tszUserName);
@@ -95,6 +97,57 @@ void CIcqProto::OnContactDeleted(MCONTACT hContact)
Push(pReq);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CIcqProto::MarkReadTimerProc(HWND hwnd, UINT, UINT_PTR id, DWORD)
+{
+ CIcqProto *ppro = (CIcqProto*)id;
+
+ mir_cslock lck(ppro->csMarkReadQueue);
+ while (ppro->arMarkReadQueue.getCount()) {
+ IcqCacheItem *pUser = ppro->arMarkReadQueue[0];
+
+ char buf[100];
+ itoa(ppro->getDword(pUser->m_hContact, DB_KEY_UIN), buf, 10);
+
+ auto *pReq = new AsyncHttpRequest(CONN_RAPI, REQUEST_POST, ICQ_ROBUST_SERVER);
+ JSONNode request, params; params.set_name("params");
+ params << CHAR_PARAM("sn", buf) << INT64_PARAM("lastRead", ppro->getId(pUser->m_hContact, DB_KEY_LASTMSGID));
+ request << CHAR_PARAM("method", "setDlgStateWim") << CHAR_PARAM("reqId", pReq->m_reqId)
+ << CHAR_PARAM("authToken", ppro->m_szRToken) << INT_PARAM("clientId", ppro->m_iRClientId) << params;
+ pReq->m_szParam = ptrW(json_write(&request));
+ ppro->Push(pReq);
+
+ ppro->arMarkReadQueue.remove(0);
+ }
+ KillTimer(hwnd, id);
+}
+
+int CIcqProto::OnDbEventRead(WPARAM, LPARAM hDbEvent)
+{
+ MCONTACT hContact = db_event_getContact(hDbEvent);
+ if (!hContact)
+ return 0;
+
+ // filter out only events of my protocol
+ const char *szProto = GetContactProto(hContact);
+ if (mir_strcmp(szProto, m_szModuleName))
+ return 0;
+
+ if (m_bOnline) {
+ SetTimer(g_hwndHeartbeat, UINT_PTR(this), 200, &CIcqProto::MarkReadTimerProc);
+
+ IcqCacheItem *pCache = FindContactByUIN(getDword(hContact, DB_KEY_UIN));
+ if (pCache) {
+ mir_cslock lck(csMarkReadQueue);
+ if (arMarkReadQueue.indexOf(pCache) == -1)
+ arMarkReadQueue.insert(pCache);
+ }
+ }
+ return 0;
+}
+
+
////////////////////////////////////////////////////////////////////////////////////////
// PS_AddToList - adds a contact to the contact list
diff --git a/protocols/Icq10/src/proto.h b/protocols/Icq10/src/proto.h
index da724224d8..425830b85a 100644
--- a/protocols/Icq10/src/proto.h
+++ b/protocols/Icq10/src/proto.h
@@ -76,13 +76,17 @@ class CIcqProto : public PROTO<CIcqProto>
void OnLoggedIn(void);
void OnLoggedOut(void);
MCONTACT ParseBuddyInfo(const JSONNode &buddy);
- void ParseMessage(MCONTACT hContact, const JSONNode &msg);
+ void ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &msg);
void RetrieveUserHistory(MCONTACT, __int64 startMsgId, __int64 endMsgId);
void RetrieveUserInfo(MCONTACT);
void SetServerStatus(int iNewStatus);
void ShutdownSession(void);
void StartSession(void);
+ mir_cs csMarkReadQueue;
+ LIST<IcqCacheItem> arMarkReadQueue;
+ static void CALLBACK MarkReadTimerProc(HWND hwnd, UINT, UINT_PTR id, DWORD);
+
__int64 getId(MCONTACT hContact, const char *szSetting);
void setId(MCONTACT hContact, const char *szSetting, __int64 iValue);
@@ -168,6 +172,7 @@ class CIcqProto : public PROTO<CIcqProto>
////////////////////////////////////////////////////////////////////////////////////////
// events
+ int __cdecl OnDbEventRead(WPARAM, LPARAM);
int __cdecl OnOptionsInit(WPARAM, LPARAM);
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/Icq10/src/server.cpp b/protocols/Icq10/src/server.cpp
index d67b2924a5..b868d2ff5d 100644
--- a/protocols/Icq10/src/server.cpp
+++ b/protocols/Icq10/src/server.cpp
@@ -187,21 +187,25 @@ MCONTACT CIcqProto::ParseBuddyInfo(const JSONNode &buddy)
return hContact;
}
-void CIcqProto::ParseMessage(MCONTACT hContact, const JSONNode &it)
+void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &it)
{
- CMStringA msgId(it["msgId"].as_mstring());
+ CMStringA szMsgId(it["msgId"].as_mstring());
+ __int64 msgId = _atoi64(szMsgId);
+ if (msgId > lastMsgId)
+ lastMsgId = msgId;
+
CMStringW type(it["mediaType"].as_mstring());
if (type != "text" && !type.IsEmpty())
return;
// ignore duplicates
- MEVENT hDbEvent = db_event_getById(m_szModuleName, msgId);
+ MEVENT hDbEvent = db_event_getById(m_szModuleName, szMsgId);
if (hDbEvent != 0)
return;
// skip own messages, just set the server msgid
CMStringA reqId(it["reqId"].as_mstring());
- if (CheckOwnMessage(reqId, msgId, true))
+ if (CheckOwnMessage(reqId, szMsgId, true))
return;
bool bIsOutgoing = it["outgoing"].as_bool();
@@ -209,7 +213,7 @@ void CIcqProto::ParseMessage(MCONTACT hContact, const JSONNode &it)
PROTORECVEVENT pre = {};
pre.flags = (bIsOutgoing) ? PREF_SENT : 0;
- pre.szMsgId = msgId;
+ pre.szMsgId = szMsgId;
pre.timestamp = it["time"].as_int();
pre.szMessage = szUtf;
ProtoChainRecvMsg(hContact, &pre);
@@ -452,13 +456,8 @@ void CIcqProto::OnGetUserHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pR
__int64 lastMsgId = getId(hContact, DB_KEY_LASTMSGID);
const JSONNode &results = root.results();
- for (auto &it : results["messages"]) {
- ParseMessage(hContact, it);
-
- __int64 msgId = _wtoi64(it["msgId"].as_mstring());
- if (msgId > lastMsgId)
- lastMsgId = msgId;
- }
+ for (auto &it : results["messages"])
+ ParseMessage(hContact, lastMsgId, it);
setId(hContact, DB_KEY_LASTMSGID, lastMsgId);
}
@@ -642,7 +641,6 @@ void CIcqProto::ProcessHistData(const JSONNode &ev)
DWORD dwUin = _wtol(ev["sn"].as_mstring());
MCONTACT hContact = CreateContact(dwUin, true);
-
__int64 lastMsgId = getId(hContact, DB_KEY_LASTMSGID);
__int64 srvlastId = _wtoi64(ev["lastMsgId"].as_mstring());
@@ -650,11 +648,12 @@ void CIcqProto::ProcessHistData(const JSONNode &ev)
if (lastMsgId == 0)
setId(hContact, DB_KEY_LASTMSGID, srvlastId);
// or load missing messages if any
- else if (srvlastId > lastMsgId)
+ else if (ev["unreadCnt"].as_int() > 0)
RetrieveUserHistory(hContact, srvlastId, lastMsgId);
-
+
for (auto &it : ev["tail"]["messages"])
- ParseMessage(hContact, it);
+ ParseMessage(hContact, lastMsgId, it);
+ setId(hContact, DB_KEY_LASTMSGID, lastMsgId);
}
void CIcqProto::ProcessImState(const JSONNode &ev)
diff --git a/protocols/Icq10/src/stdafx.h b/protocols/Icq10/src/stdafx.h
index 8e8ec110a4..a6636ebf84 100644
--- a/protocols/Icq10/src/stdafx.h
+++ b/protocols/Icq10/src/stdafx.h
@@ -89,3 +89,5 @@
#include "proto.h"
int StatusFromString(const CMStringW&);
+
+extern HWND g_hwndHeartbeat; \ No newline at end of file