From dc2267b1fb5bc6e43914f7a0709fbe48bf4b9a09 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 7 Jan 2019 16:29:37 +0200 Subject: ICQ: connection manager (must fix #1728 completely) --- protocols/Icq10/src/http.cpp | 44 ++++++++++++++++++++++++++++-------------- protocols/Icq10/src/proto.h | 8 +++++++- protocols/Icq10/src/server.cpp | 10 +++++----- 3 files changed, 42 insertions(+), 20 deletions(-) (limited to 'protocols') diff --git a/protocols/Icq10/src/http.cpp b/protocols/Icq10/src/http.cpp index 4b560b6617..51ad947e26 100644 --- a/protocols/Icq10/src/http.cpp +++ b/protocols/Icq10/src/http.cpp @@ -35,7 +35,6 @@ void __cdecl CIcqProto::ServerThread(void*) break; AsyncHttpRequest *pReq; - bool need_sleep = false; while (true) { { mir_cslock lck(m_csHttpQueue); @@ -44,24 +43,29 @@ void __cdecl CIcqProto::ServerThread(void*) pReq = m_arHttpQueue[0]; m_arHttpQueue.remove(0); - need_sleep = (m_arHttpQueue.getCount() > 1); } if (m_bTerminated) break; ExecuteRequest(pReq); - if (need_sleep) { - Sleep(330); - debugLogA("CIcqProto::WorkerThread: %s", "need to sleep"); + } + + int ts = time(0); + for (auto &it : m_ConnPool) { + if (it.s && it.lastTs + it.timeout < ts) { + Netlib_CloseHandle(it.s); + it.s = nullptr; + it.lastTs = 0; } } } m_hWorkerThread = nullptr; - for (auto &it : m_ConnPool) - if (it) { - Netlib_CloseHandle(it); - it = nullptr; - } + for (auto &it : m_ConnPool) { + if (it.s) + Netlib_CloseHandle(it.s); + it.s = nullptr; + it.lastTs = it.timeout = 0; + } debugLogA("CIcqProto::WorkerThread: %s", "leaving"); } @@ -110,7 +114,8 @@ void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) if (pReq->m_conn != CONN_NONE) { pReq->flags |= NLHRF_PERSISTENT; - pReq->nlc = m_ConnPool[pReq->m_conn]; + pReq->nlc = m_ConnPool[pReq->m_conn].s; + m_ConnPool[pReq->m_conn].lastTs = time(0); } debugLogA("Executing request %s:\n%s", pReq->m_reqId, pReq->szUrl); @@ -151,8 +156,19 @@ void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) if (pReq->m_pFunc != nullptr) (this->*(pReq->m_pFunc))(reply, pReq); - if (pReq->m_conn != CONN_NONE) - m_ConnPool[pReq->m_conn] = reply->nlc; + if (pReq->m_conn != CONN_NONE) { + auto &conn = m_ConnPool[pReq->m_conn]; + conn.s = reply->nlc; + conn.timeout = 0; + for (int i = 0; i < reply->headersCount; i++) { + if (!mir_strcmp(reply->headers[i].szName, "Keep-Alive")) { + int timeout; + if (1 == sscanf(reply->headers[i].szValue, "timeout=%d", &timeout)) + conn.timeout = timeout; + break; + } + } + } Netlib_FreeHttpRequest(reply); } @@ -162,7 +178,7 @@ void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) if (pReq->m_conn != CONN_NONE) { if (IsStatusConnecting(m_iStatus)) ConnectionFailed(LOGINERR_NONETWORK); - m_ConnPool[pReq->m_conn] = nullptr; + m_ConnPool[pReq->m_conn].s = nullptr; } } diff --git a/protocols/Icq10/src/proto.h b/protocols/Icq10/src/proto.h index 425830b85a..53a27f80a1 100644 --- a/protocols/Icq10/src/proto.h +++ b/protocols/Icq10/src/proto.h @@ -62,6 +62,12 @@ struct IcqOwnMessage char m_guid[50]; }; +struct IcqConn +{ + HNETLIBCONN s; + int lastTs, timeout; +}; + class CIcqProto : public PROTO { friend struct CIcqRegistrationDlg; @@ -113,7 +119,7 @@ class CIcqProto : public PROTO void ProcessPresence(const JSONNode&); void ProcessTyping(const JSONNode&); - HNETLIBCONN m_ConnPool[CONN_LAST]; + IcqConn m_ConnPool[CONN_LAST]; CMStringA m_szSessionKey; CMStringA m_szAToken; CMStringA m_szRToken; diff --git a/protocols/Icq10/src/server.cpp b/protocols/Icq10/src/server.cpp index b868d2ff5d..1d5bda5521 100644 --- a/protocols/Icq10/src/server.cpp +++ b/protocols/Icq10/src/server.cpp @@ -232,7 +232,7 @@ bool CIcqProto::RefreshRobustToken() << CHAR_PARAM("nonce", CMStringA(FORMAT, "%d-%d", ts, rand() % 10)) << INT_PARAM("ts", ts); CalcHash(tmp); tmp->flags |= NLHRF_PERSISTENT; - tmp->nlc = m_ConnPool[CONN_RAPI]; + tmp->nlc = m_ConnPool[CONN_RAPI].s; tmp->dataLength = tmp->m_szParam.GetLength(); tmp->pData = tmp->m_szParam.Detach(); tmp->szUrl = tmp->m_szUrl.GetBuffer(); @@ -241,7 +241,7 @@ bool CIcqProto::RefreshRobustToken() tmp->AddHeader("User-Agent", szAgent); NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, tmp); - m_ConnPool[CONN_RAPI] = nullptr; + m_ConnPool[CONN_RAPI].s = nullptr; if (reply != nullptr) { RobustReply result(reply); if (result.error() == 20000) { @@ -258,7 +258,7 @@ bool CIcqProto::RefreshRobustToken() ExecuteRequest(add); } - m_ConnPool[CONN_RAPI] = reply->nlc; + m_ConnPool[CONN_RAPI].s = reply->nlc; Netlib_FreeHttpRequest(reply); } @@ -336,8 +336,8 @@ void CIcqProto::ShutdownSession() SetEvent(m_evRequestsQueue); for (auto &it : m_ConnPool) - if (it) - Netlib_Shutdown(it); + if (it.s) + Netlib_Shutdown(it.s); OnLoggedOut(); } -- cgit v1.2.3