From 49319f4436166dec8bc3532bea1f20fa07c5af24 Mon Sep 17 00:00:00 2001 From: ElzorFox Date: Mon, 3 Mar 2025 17:25:25 +0500 Subject: VKontakte: rework retrieve requests processing sending the captcha result as a separate request no captcha form for longpool process version bump --- protocols/VKontakte/src/misc.cpp | 23 +++--- protocols/VKontakte/src/version.h | 2 +- protocols/VKontakte/src/vk_captcha.cpp | 32 +++++---- protocols/VKontakte/src/vk_proto.cpp | 1 + protocols/VKontakte/src/vk_proto.h | 8 ++- protocols/VKontakte/src/vk_queue.cpp | 127 +++++++++++++++++++-------------- protocols/VKontakte/src/vk_struct.h | 2 +- 7 files changed, 107 insertions(+), 88 deletions(-) (limited to 'protocols') diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index cb516b4479..b407cb7ac4 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -393,20 +393,16 @@ bool CVkProto::CheckJsonResult(AsyncHttpRequest *pReq, const JSONNode &jnNode) MsgPopup(TranslateT("Access denied! Data will not be sent or received."), TranslateT("Error"), true); break; case VKERR_CAPTCHA_NEEDED: + if (!pReq) + return false; + if (!ApplyCaptcha(pReq, jnError)) - if(pReq->m_iRetry > 0) { - pReq->bNeedsRestart = true; - Sleep(1000); - debugLogA("CVkProto::CheckJsonResult Captcha processing error."); - debugLogA("CVkProto::CheckJsonResult Retry = %d", pReq->m_iRetry); - pReq->m_iRetry--; - } - else { + if(!pReq->m_iRetry) { CMStringW wszMsg(FORMAT, TranslateT("Error %d. Data will not be sent or received."), iErrorCode); wszMsg += "\n"; wszMsg += TranslateT("Captcha processing error."); MsgPopup(wszMsg, TranslateT("Error"), true); - debugLogA("CVkProto::CheckJsonResult SendError"); + debugLogA("CVkProto::CheckJsonResult Captcha processing error"); } break; @@ -426,12 +422,13 @@ bool CVkProto::CheckJsonResult(AsyncHttpRequest *pReq, const JSONNode &jnNode) case VKERR_UNKNOWN: case VKERR_TOO_MANY_REQ_PER_SEC: + if (pReq->m_priority == AsyncHttpRequest::rpCaptcha) + break; + __fallthrough; case VKERR_INTERNAL_SERVER_ERR: if (pReq->m_iRetry > 0) { pReq->bNeedsRestart = true; - Sleep(1000); //Pause for fix err - debugLogA("CVkProto::CheckJsonResult Retry = %d", pReq->m_iRetry); - pReq->m_iRetry--; + debugLogA("CVkProto::CheckJsonResult Retry = %d", (MAX_RETRIES - pReq->m_iRetry + 1)); } else { CMStringW wszMsg(FORMAT, TranslateT("Error %d. Data will not be sent or received."), iErrorCode); @@ -659,7 +656,7 @@ void CVkProto::GrabCookies(MHttpResponse *nhr, CMStringA szDefDomain) SaveCookies(); } -void CVkProto::ApplyCookies(AsyncHttpRequest *pReq) +void CVkProto::ApplyCookies(MHttpRequest *pReq) { debugLogA("CVkProto::ApplyCookies"); CMStringA szCookie; diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h index b9d0306f1f..8f8e165fa4 100644 --- a/protocols/VKontakte/src/version.h +++ b/protocols/VKontakte/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 1 #define __RELEASE_NUM 18 -#define __BUILD_NUM 4 +#define __BUILD_NUM 5 #include diff --git a/protocols/VKontakte/src/vk_captcha.cpp b/protocols/VKontakte/src/vk_captcha.cpp index 7162a4cb11..90b4db548e 100644 --- a/protocols/VKontakte/src/vk_captcha.cpp +++ b/protocols/VKontakte/src/vk_captcha.cpp @@ -69,31 +69,33 @@ bool CVkProto::RunCaptchaForm(LPCSTR szUrl, CMStringA &result) bool CVkProto::ApplyCaptcha(AsyncHttpRequest *pReq, const JSONNode &jnErrorNode) { debugLogA("CVkProto::ApplyCaptcha"); + if (m_bCaptchaReqInProgress) + return true; + + m_bCaptchaReqInProgress = true; CMStringA szUrl(jnErrorNode["captcha_img"].as_mstring()); CMStringA szSid(jnErrorNode["captcha_sid"].as_mstring()); - if (szUrl.IsEmpty() || szSid.IsEmpty()) + if (szUrl.IsEmpty() || szSid.IsEmpty()) { + m_bCaptchaReqInProgress = false; return false; + } CMStringA userReply; - if (!RunCaptchaForm(szUrl, userReply)) + if (!RunCaptchaForm(szUrl, userReply)) { + m_bCaptchaReqInProgress = false; return false; + } - CMStringA szCapthaStr(FORMAT, "&captcha_sid=%s&captcha_key=%s", mir_urlEncode(szSid).c_str(), mir_urlEncode(userReply.GetString()).c_str()); - - int iCaptchaBeg = pReq->m_szUrl.Find("&captcha_sid=", 0); - int iCaptchaEnd = pReq->m_szUrl.Find("&v=", 0); - - if ((iCaptchaBeg > -1) && (iCaptchaEnd > iCaptchaBeg)) - pReq->m_szUrl.Replace(pReq->m_szUrl.Mid(iCaptchaBeg, iCaptchaEnd - iCaptchaBeg).c_str(), szCapthaStr); - else if (iCaptchaEnd > -1) - pReq->m_szUrl.Replace("&v=", szCapthaStr + "&v="); - else - pReq->m_szUrl += szCapthaStr; + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/account.setOnline.json", true, &CVkProto::OnReceiveSmth, AsyncHttpRequest::rpCaptcha) + << CHAR_PARAM("captcha_sid", szSid) + << CHAR_PARAM("captcha_key", userReply.GetString()) + ); pReq->bNeedsRestart = true; - debugLogA("CVkProto::ApplyCaptcha %s", pReq->m_szUrl); - + debugLogA("CVkProto::ApplyCaptcha for %s", pReq->m_szUrl.c_str()); + m_bCaptchaReqInProgress = false; + return true; } \ No newline at end of file diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index 0a6dd5525a..462de8a9d1 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -41,6 +41,7 @@ CVkProto::CVkProto(const char *szModuleName, const wchar_t *pwszUserName) : m_bSetBroadcast(false), m_bNeedSendOnline(false), m_bErr404Return(false), + m_bCaptchaReqInProgress(false), m_vkOptions(this) { bIint64IDCompatibility = getBool("Iint64IDCompatibility"); diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 6feaa2685a..a6fa6d1f69 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -46,7 +46,7 @@ along with this program. If not, see . #define MAXHISTORYMIDSPERONE 100 -#define MAX_RETRIES 20 +#define MAX_RETRIES 10 #define MAX_CONTACTS_PER_REQUEST 530 struct CVkProto : public PROTO @@ -213,7 +213,8 @@ private: m_bNotifyForEndLoadingHistory, m_bNotifyForEndLoadingHistoryAllContact, m_bTerminated, - m_bErr404Return; + m_bErr404Return, + m_bCaptchaReqInProgress; VKUserID_t m_iMyUserId; @@ -380,7 +381,7 @@ private: CMStringW RunConfirmationCode(LPCWSTR pwszTitle); CMStringW RunRenameNick(LPCWSTR pwszOldName); void GrabCookies(MHttpResponse *nhr, CMStringA szDefDomain = ""); - void ApplyCookies(AsyncHttpRequest*); + void ApplyCookies(MHttpRequest*); void SaveCookies(); void LoadCookies(); bool IsAuthContactLater(MCONTACT hContact); @@ -417,6 +418,7 @@ private: void InitQueue(); void UninitQueue(); bool ExecuteRequest(AsyncHttpRequest*); + bool RestartRequest(AsyncHttpRequest*); void __cdecl WorkerThread(void*); AsyncHttpRequest* Push(MHttpRequest *pReq, int iTimeout = 10000); bool RunCaptchaForm(LPCSTR szUrl, CMStringA&); diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index 28c3a5b361..d8cd125e2b 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -34,69 +34,85 @@ void CVkProto::UninitQueue() bool CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) { - do { - pReq->bNeedsRestart = false; - pReq->m_iErrorCode = 0; - - if (pReq->m_bApiReq) { - pReq->flags |= NLHRF_PERSISTENT; - pReq->nlc = m_hAPIConnection; - } + pReq->bNeedsRestart = false; + pReq->m_iErrorCode = 0; - if (m_bTerminated) - break; + if (pReq->m_bApiReq) { + pReq->flags |= NLHRF_PERSISTENT; + pReq->nlc = m_hAPIConnection; + } - time_t tLocalWorkThreadTimer = 0; - { - mir_cslock lck(m_csWorkThreadTimer); - tLocalWorkThreadTimer = m_tWorkThreadTimer = time(0); - if (pReq->m_bApiReq) - ApplyCookies(pReq); - } + if (m_bTerminated) { + delete pReq; + return false; + } - debugLogA("CVkProto::ExecuteRequest \n====\n%s\n====\n", pReq->m_szUrl.c_str()); - NLHR_PTR reply(Netlib_HttpTransaction(m_hNetlibUser, pReq)); - { - mir_cslock lck(m_csWorkThreadTimer); - if (pReq->m_bApiReq) - GrabCookies(reply, "api.vk.com"); - - if (tLocalWorkThreadTimer != m_tWorkThreadTimer) { - debugLogA("CVkProto::WorkerThread is living Dead => return"); - delete pReq; - return false; - } + time_t tLocalWorkThreadTimer = 0; + { + mir_cslock lck(m_csWorkThreadTimer); + tLocalWorkThreadTimer = m_tWorkThreadTimer = time(0); + if (pReq->m_bApiReq) + ApplyCookies(pReq); + } + + debugLogA("CVkProto::ExecuteRequest \n====\n%s\n====\n", pReq->m_szUrl.c_str()); + NLHR_PTR reply(Netlib_HttpTransaction(m_hNetlibUser, pReq)); + { + mir_cslock lck(m_csWorkThreadTimer); + if (pReq->m_bApiReq) + GrabCookies(reply, "api.vk.com"); + + if (tLocalWorkThreadTimer != m_tWorkThreadTimer) { + debugLogA("CVkProto::WorkerThread is living Dead => return"); + delete pReq; + return false; } + } - if (reply != nullptr) { - if (pReq->m_pFunc != nullptr) - (this->*(pReq->m_pFunc))(reply, pReq); // may be set pReq->bNeedsRestart + if (reply != nullptr) { + if (pReq->m_pFunc != nullptr) + (this->*(pReq->m_pFunc))(reply, pReq); // may be set pReq->bNeedsRestart - if (pReq->m_bApiReq) - m_hAPIConnection = reply->nlc; - } - else if (pReq->bIsMainConn) { - if (IsStatusConnecting(m_iStatus)) - ConnectionFailed(LOGINERR_NONETWORK); - else if (pReq->m_iRetry && !m_bTerminated) { - pReq->bNeedsRestart = true; - Sleep(1000); //Pause for fix err - pReq->m_iRetry--; - debugLogA("CVkProto::ExecuteRequest restarting (retry = %d)", MAX_RETRIES - pReq->m_iRetry); - } - else { - debugLogA("CVkProto::ExecuteRequest ShutdownSession"); - ShutdownSession(); - } + if (pReq->m_bApiReq) + m_hAPIConnection = reply->nlc; + } + else if (pReq->bIsMainConn) { + if (IsStatusConnecting(m_iStatus)) + ConnectionFailed(LOGINERR_NONETWORK); + else if (pReq->m_iRetry && !m_bTerminated) + pReq->bNeedsRestart = true; + else { + debugLogA("CVkProto::ExecuteRequest ShutdownSession"); + ShutdownSession(); + return false; } - debugLogA("CVkProto::ExecuteRequest pReq->bNeedsRestart = %d", (int)pReq->bNeedsRestart); + } + + if (pReq->bNeedsRestart) + RestartRequest(pReq); + else + delete pReq; + + return true; +} + +bool CVkProto::RestartRequest(AsyncHttpRequest* pReq) +{ + debugLogA("CVkProto::RestartRequest %d %s", (MAX_RETRIES - pReq->m_iRetry + 1), pReq->m_szUrl.c_str()); + + if (m_bTerminated || !pReq->m_iRetry) { + ShutdownSession(); + delete pReq; + pReq = nullptr; + return false; + } - if (!reply && pReq->m_bApiReq) - CloseAPIConnection(); + pReq->bNeedsRestart = false; + pReq->m_priority = AsyncHttpRequest::RequestPriority::rpRestart; + pReq->m_iRetry--; - } while (pReq->bNeedsRestart && !m_bTerminated); - delete pReq; - return true; + Push(pReq); + } ///////////////////////////////////////////////////////////////////////////////////////// @@ -107,7 +123,8 @@ AsyncHttpRequest* CVkProto::Push(MHttpRequest *p, int iTimeout) debugLogA("CVkProto::Push"); pReq->timeout = iTimeout; - if (pReq->m_bApiReq) { + + if (pReq->m_bApiReq && (pReq->m_iRetry == MAX_RETRIES)) { pReq << VER_API; if (!IsEmpty(m_vkOptions.pwszVKLang)) pReq << WCHAR_PARAM("lang", m_vkOptions.pwszVKLang); diff --git a/protocols/VKontakte/src/vk_struct.h b/protocols/VKontakte/src/vk_struct.h index 168c79e925..aac60bf2ef 100644 --- a/protocols/VKontakte/src/vk_struct.h +++ b/protocols/VKontakte/src/vk_struct.h @@ -20,7 +20,7 @@ along with this program. If not, see . struct AsyncHttpRequest : public MTHttpRequest { - enum RequestPriority { rpLowLow, rpLow, rpMedium, rpHigh }; + enum RequestPriority { rpLowLow, rpLow, rpMedium, rpHigh, rpRestart, rpCaptcha }; AsyncHttpRequest(); AsyncHttpRequest(CVkProto*, int iRequestType, LPCSTR szUrl, bool bSecure, MTHttpRequestHandler pFunc, RequestPriority rpPriority = rpMedium); -- cgit v1.2.3