From 8ed8b8bee2fa6abdfaa4b92543070baef0f340cb Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 23 Oct 2013 19:03:18 +0000 Subject: - fix for the old & nasty bug in netlib that rarely crashed Facebook & VK - code cleaning git-svn-id: http://svn.miranda-ng.org/main/trunk@6602 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/modules/netlib/netlib.cpp | 196 ++++++++++++++++++-------------------- src/modules/netlib/netlib.h | 2 +- src/modules/netlib/netlibhttp.cpp | 3 + 3 files changed, 96 insertions(+), 105 deletions(-) (limited to 'src/modules/netlib') diff --git a/src/modules/netlib/netlib.cpp b/src/modules/netlib/netlib.cpp index 5825bc9801..b6deb4aef6 100644 --- a/src/modules/netlib/netlib.cpp +++ b/src/modules/netlib/netlib.cpp @@ -52,6 +52,17 @@ void NetlibFreeUserSettingsStruct(NETLIBUSERSETTINGS *settings) mir_free(settings->szProxyServer); } +int GetNetlibHandleType(void *p) +{ + __try { + return *(int*)p; + } + __except(EXCEPTION_EXECUTE_HANDLER) + {} + + return NLH_INVALID; +} + void NetlibInitializeNestedCS(NetlibNestedCriticalSection *nlncs) { nlncs->dwOwningThreadId = 0; @@ -103,9 +114,9 @@ void NetlibLeaveNestedCS(NetlibNestedCriticalSection *nlncs) static INT_PTR GetNetlibUserSettingInt(const char *szUserModule, const char *szSetting, int defValue) { DBVARIANT dbv; - if (db_get(NULL, szUserModule, szSetting, &dbv) - && db_get(NULL, "Netlib", szSetting, &dbv)) + if (db_get(NULL, szUserModule, szSetting, &dbv) && db_get(NULL, "Netlib", szSetting, &dbv)) return defValue; + if (dbv.type == DBVT_BYTE) return dbv.bVal; if (dbv.type == DBVT_WORD) return dbv.wVal; return dbv.dVal; @@ -114,26 +125,23 @@ static INT_PTR GetNetlibUserSettingInt(const char *szUserModule, const char *szS static char *GetNetlibUserSettingString(const char *szUserModule, const char *szSetting, int decode) { DBVARIANT dbv; - if (db_get_s(NULL, szUserModule, szSetting, &dbv) - && db_get_s(NULL, "Netlib", szSetting, &dbv)) { + if (db_get_s(NULL, szUserModule, szSetting, &dbv) && db_get_s(NULL, "Netlib", szSetting, &dbv)) return NULL; - } - else { - char *szRet; - if (decode) CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal) + 1, (LPARAM)dbv.pszVal); - szRet = mir_strdup(dbv.pszVal); - db_free(&dbv); - if (szRet == NULL) SetLastError(ERROR_OUTOFMEMORY); - return szRet; - } + + if (decode) CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal) + 1, (LPARAM)dbv.pszVal); + char *szRet = mir_strdup(dbv.pszVal); + db_free(&dbv); + if (szRet == NULL) SetLastError(ERROR_OUTOFMEMORY); + return szRet; } static INT_PTR NetlibRegisterUser(WPARAM, LPARAM lParam) { NETLIBUSER *nlu = (NETLIBUSER*)lParam; - if (nlu == NULL || nlu->cbSize != sizeof(NETLIBUSER) || nlu->szSettingsModule == NULL - || ( !(nlu->flags&NUF_NOOPTIONS) && nlu->szDescriptiveName == NULL) - || (nlu->flags&NUF_HTTPGATEWAY && (nlu->pfnHttpGatewayInit == NULL))) { + if (nlu == NULL || nlu->cbSize != sizeof(NETLIBUSER) || nlu->szSettingsModule == NULL || + (!(nlu->flags & NUF_NOOPTIONS) && nlu->szDescriptiveName == NULL) || + (nlu->flags & NUF_HTTPGATEWAY && (nlu->pfnHttpGatewayInit == NULL))) + { SetLastError(ERROR_INVALID_PARAMETER); return 0; } @@ -153,9 +161,9 @@ static INT_PTR NetlibRegisterUser(WPARAM, LPARAM lParam) return 0; } - if (nlu->szDescriptiveName) { + if (nlu->szDescriptiveName) thisUser->user.ptszDescriptiveName = (thisUser->user.flags&NUF_UNICODE ? mir_u2t((WCHAR*)nlu->ptszDescriptiveName) : mir_a2t(nlu->szDescriptiveName)); - } + if ((thisUser->user.szSettingsModule = mir_strdup(nlu->szSettingsModule)) == NULL || (nlu->szDescriptiveName && thisUser->user.ptszDescriptiveName == NULL) || (nlu->szHttpGatewayUserAgent && (thisUser->user.szHttpGatewayUserAgent = mir_strdup(nlu->szHttpGatewayUserAgent)) == NULL)) @@ -229,8 +237,7 @@ void NetlibDoClose(NetlibConnection *nlc, bool noShutdown) if (nlc->s == INVALID_SOCKET) return; NetlibLogf(nlc->nlu, "(%p:%u) Connection closed internal", nlc, nlc->s); - if (nlc->hSsl) - { + if (nlc->hSsl) { if ( !noShutdown) si.shutdown(nlc->hSsl); si.sfree(nlc->hSsl); nlc->hSsl = NULL; @@ -241,9 +248,8 @@ void NetlibDoClose(NetlibConnection *nlc, bool noShutdown) INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) { - switch(GetNetlibHandleType(wParam)) - { - case NLH_USER: + switch(GetNetlibHandleType((void*)wParam)) { + case NLH_USER: { NetlibUser *nlu = (NetlibUser*)wParam; { @@ -261,7 +267,7 @@ INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) mir_free(nlu->szStickyHeaders); break; } - case NLH_CONNECTION: + case NLH_CONNECTION: { NetlibConnection *nlc = (struct NetlibConnection*)wParam; HANDLE waitHandles[4]; @@ -269,14 +275,10 @@ INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) WaitForSingleObject(hConnectionHeaderMutex, INFINITE); if (nlc->usingHttpGateway) - { HttpGatewayRemovePacket(nlc, -1); - } - else - { - if (nlc->s != INVALID_SOCKET) { + else { + if (nlc->s != INVALID_SOCKET) NetlibDoClose(nlc); - } if (nlc->s2 != INVALID_SOCKET) closesocket(nlc->s2); nlc->s2 = INVALID_SOCKET; } @@ -305,19 +307,22 @@ INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) DeleteCriticalSection(&nlc->csHttpSequenceNums); ReleaseMutex(hConnectionHeaderMutex); NetlibLogf(nlc->nlu, "(%p:%u) Connection closed", nlc, nlc->s); - break; } - case NLH_BOUNDPORT: - return NetlibFreeBoundPort((struct NetlibBoundPort*)wParam); - case NLH_PACKETRECVER: + break; + + case NLH_BOUNDPORT: + return NetlibFreeBoundPort((struct NetlibBoundPort*)wParam); + + case NLH_PACKETRECVER: { struct NetlibPacketRecver *nlpr = (struct NetlibPacketRecver*)wParam; mir_free(nlpr->packetRecver.buffer); - break; } - default: - SetLastError(ERROR_INVALID_PARAMETER); - return 0; + break; + + default: + SetLastError(ERROR_INVALID_PARAMETER); + return 0; } mir_free((void*)wParam); return 1; @@ -326,26 +331,23 @@ INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) static INT_PTR NetlibGetSocket(WPARAM wParam, LPARAM) { SOCKET s; - if (wParam == 0) - { + if (wParam == 0) { s = INVALID_SOCKET; SetLastError(ERROR_INVALID_PARAMETER); } - else - { + else { WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - switch (GetNetlibHandleType(wParam)) - { - case NLH_CONNECTION: - s = ((struct NetlibConnection*)wParam)->s; - break; - case NLH_BOUNDPORT: - s = ((struct NetlibBoundPort*)wParam)->s; - break; - default: - s = INVALID_SOCKET; - SetLastError(ERROR_INVALID_PARAMETER); - break; + switch (GetNetlibHandleType((void*)wParam)) { + case NLH_CONNECTION: + s = ((struct NetlibConnection*)wParam)->s; + break; + case NLH_BOUNDPORT: + s = ((struct NetlibBoundPort*)wParam)->s; + break; + default: + s = INVALID_SOCKET; + SetLastError(ERROR_INVALID_PARAMETER); + break; } ReleaseMutex(hConnectionHeaderMutex); } @@ -381,58 +383,51 @@ INT_PTR NetlibGetMyIp(WPARAM wParam, LPARAM) INT_PTR NetlibShutdown(WPARAM wParam, LPARAM) { - if (wParam) - { + if (wParam) { WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - switch(GetNetlibHandleType(wParam)) { - case NLH_CONNECTION: - { - struct NetlibConnection* nlc = (struct NetlibConnection*)wParam; - if (nlc->hSsl) si.shutdown(nlc->hSsl); - if (nlc->s != INVALID_SOCKET) shutdown(nlc->s, 2); - if (nlc->s2 != INVALID_SOCKET) shutdown(nlc->s2, 2); - nlc->termRequested = true; - } - break; - case NLH_BOUNDPORT: - { - struct NetlibBoundPort* nlb = (struct NetlibBoundPort*)wParam; - if (nlb->s != INVALID_SOCKET) shutdown(nlb->s, 2); - } - break; + switch(GetNetlibHandleType((void*)wParam)) { + case NLH_CONNECTION: + { + struct NetlibConnection* nlc = (struct NetlibConnection*)wParam; + if (nlc->hSsl) si.shutdown(nlc->hSsl); + if (nlc->s != INVALID_SOCKET) shutdown(nlc->s, 2); + if (nlc->s2 != INVALID_SOCKET) shutdown(nlc->s2, 2); + nlc->termRequested = true; + } + break; + case NLH_BOUNDPORT: + { + struct NetlibBoundPort* nlb = (struct NetlibBoundPort*)wParam; + if (nlb->s != INVALID_SOCKET) shutdown(nlb->s, 2); + } + break; } ReleaseMutex(hConnectionHeaderMutex); - } return 0; } void UnloadNetlibModule(void) { - if ( !bModuleInitialized) return; - - if (hConnectionHeaderMutex != NULL) - { - int i; + if (!bModuleInitialized || hConnectionHeaderMutex == NULL) return; - NetlibUnloadIeProxy(); - NetlibSecurityDestroy(); - NetlibUPnPDestroy(); - NetlibLogShutdown(); + NetlibUnloadIeProxy(); + NetlibSecurityDestroy(); + NetlibUPnPDestroy(); + NetlibLogShutdown(); - DestroyHookableEvent(hRecvEvent); hRecvEvent = NULL; - DestroyHookableEvent(hSendEvent); hSendEvent = NULL; + DestroyHookableEvent(hRecvEvent); hRecvEvent = NULL; + DestroyHookableEvent(hSendEvent); hSendEvent = NULL; - for (i = netlibUser.getCount(); i > 0; i--) - NetlibCloseHandle((WPARAM)netlibUser[i-1], 0); + for (int i = netlibUser.getCount(); i > 0; i--) + NetlibCloseHandle((WPARAM)netlibUser[i-1], 0); - netlibUser.destroy(); + netlibUser.destroy(); - CloseHandle(hConnectionHeaderMutex); - if (hConnectionOpenMutex) CloseHandle(hConnectionOpenMutex); - DeleteCriticalSection(&csNetlibUser); - WSACleanup(); - } + CloseHandle(hConnectionHeaderMutex); + if (hConnectionOpenMutex) CloseHandle(hConnectionOpenMutex); + DeleteCriticalSection(&csNetlibUser); + WSACleanup(); } int LoadNetlibModule(void) @@ -453,19 +448,16 @@ int LoadNetlibModule(void) OSVERSIONINFOEX osvi = {0}; osvi.dwOSVersionInfoSize = sizeof(osvi); - if (GetVersionEx((LPOSVERSIONINFO)&osvi)) - { + if (GetVersionEx((LPOSVERSIONINFO)&osvi)) { // Connection limiting was introduced in Windows XP SP2 and later and set to 10 / sec if (osvi.dwMajorVersion == 5 && ((osvi.dwMinorVersion == 1 && osvi.wServicePackMajor >= 2) || osvi.dwMinorVersion > 1)) connectionTimeout = 150; // Connection limiting has limits based on addition Windows Vista pre SP2 - else if (osvi.dwMajorVersion == 6 && osvi.wServicePackMajor < 2) - { + else if (osvi.dwMajorVersion == 6 && osvi.wServicePackMajor < 2) { DWORD dwType = 0; tGetProductInfo pGetProductInfo = (tGetProductInfo) GetProcAddress(GetModuleHandleA("kernel32"), "GetProductInfo"); if (pGetProductInfo != NULL) pGetProductInfo(6, 0, 0, 0, &dwType); - switch(dwType) - { + switch(dwType) { case 0x01: // Vista Ultimate edition have connection limit of 25 / sec - plenty for Miranda case 0x1c: break; @@ -481,21 +473,18 @@ int LoadNetlibModule(void) } } // Connection limiting is disabled by default and is controlled by registry setting in Windows Vista SP2 and later - else if (osvi.dwMajorVersion >= 6) - { + else if (osvi.dwMajorVersion >= 6) { static const char keyn[] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"; static const char valn[] = "EnableConnectionRateLimiting"; HKEY hSettings; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyn, 0, KEY_QUERY_VALUE, &hSettings) == ERROR_SUCCESS) - { + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyn, 0, KEY_QUERY_VALUE, &hSettings) == ERROR_SUCCESS) { DWORD tValueLen, enabled; tValueLen = sizeof(enabled); if (RegQueryValueExA(hSettings, valn, NULL, NULL, (BYTE*)&enabled, &tValueLen) == ERROR_SUCCESS && enabled) connectionTimeout = 150; // if enabled limit is set to 10 / sec RegCloseKey(hSettings); } - } } @@ -535,7 +524,6 @@ int LoadNetlibModule(void) NetlibUPnPInit(); NetlibSecurityInit(); NetlibLoadIeProxy(); - return 0; } diff --git a/src/modules/netlib/netlib.h b/src/modules/netlib/netlib.h index 290d9b44b6..0108604f6b 100644 --- a/src/modules/netlib/netlib.h +++ b/src/modules/netlib/netlib.h @@ -21,12 +21,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define GetNetlibHandleType(h) (h?*(int*)h:NLH_INVALID) #define NLH_INVALID 0 #define NLH_USER 'USER' #define NLH_CONNECTION 'CONN' #define NLH_BOUNDPORT 'BIND' #define NLH_PACKETRECVER 'PCKT' +int GetNetlibHandleType(void*); struct NetlibUser { diff --git a/src/modules/netlib/netlibhttp.cpp b/src/modules/netlib/netlibhttp.cpp index 9aafc3d066..1022e63e69 100644 --- a/src/modules/netlib/netlibhttp.cpp +++ b/src/modules/netlib/netlibhttp.cpp @@ -839,6 +839,9 @@ INT_PTR NetlibHttpTransaction(WPARAM wParam, LPARAM lParam) return 0; } + if (nlhr->nlc != NULL && GetNetlibHandleType(nlhr->nlc) != NLH_CONNECTION) + nlhr->nlc = NULL; + NetlibConnection* nlc = NetlibHttpProcessUrl(nlhr, nlu, (NetlibConnection*)nlhr->nlc); if (nlc == NULL) return 0; -- cgit v1.2.3