DWORD CMraProto::MraMrimProxyConnect(HANDLE hMraMrimProxyData, HANDLE *phConnection) { DWORD dwRetErrorCode; if (hMraMrimProxyData && phConnection) { BOOL bIsHTTPSProxyUsed, bContinue; BYTE lpbBufferRcv[BUFF_SIZE_RCV_MIN_FREE]; DWORD dwBytesReceived, dwConnectReTryCount, dwCurConnectReTryCount; size_t dwRcvBuffSize = BUFF_SIZE_RCV_MIN_FREE, dwRcvBuffSizeUsed; NETLIBSELECT nls = {0}; MRA_MRIMPROXY_DATA *pmmpd = (MRA_MRIMPROXY_DATA*)hMraMrimProxyData; NETLIBOPENCONNECTION nloc = {0}; // адреса есть, значит инициаторы не мы if (pmmpd->malAddrList.dwAddrCount) { CMStringA szAddresses = MraAddrListGetToBuff(&pmmpd->malAddrList); MraProxyAck(PROXY_STATUS_OK, pmmpd->szEmail, pmmpd->dwIDRequest, pmmpd->dwDataType, pmmpd->lpszUserData, szAddresses, pmmpd->mguidSessionID); } // мы инициаторы else { pmmpd->hWaitHandle = CreateEvent(NULL, TRUE, FALSE, NULL); if (pmmpd->szEmail) if (MraProxy(pmmpd->szEmail, pmmpd->dwIDRequest, pmmpd->dwDataType, pmmpd->lpszUserData, "", pmmpd->mguidSessionID)) WaitForSingleObjectEx(pmmpd->hWaitHandle, INFINITE, FALSE); CloseHandle(pmmpd->hWaitHandle); pmmpd->hWaitHandle = NULL; } dwRetErrorCode = ERROR_NO_NETWORK; if (pmmpd->malAddrList.dwAddrCount) { pmmpd->hConnection = NULL; bIsHTTPSProxyUsed = IsHTTPSProxyUsed(m_hNetlibUser); dwConnectReTryCount = getDword("ConnectReTryCountMRIMProxy", MRA_DEFAULT_CONN_RETRY_COUNT_MRIMPROXY); nloc.cbSize = sizeof(nloc); nloc.flags = NLOCF_V2; nloc.timeout = ((MRA_TIMEOUT_DIRECT_CONN-1)/(pmmpd->malAddrList.dwAddrCount*dwConnectReTryCount));// -1 сек чтобы был запас if (nloc.timeout < MRA_TIMEOUT_CONN_MIN) nloc.timeout = MRA_TIMEOUT_CONN_MIN; if (nloc.timeout > MRA_TIMEOUT_CONN_MAX) nloc.timeout = MRA_TIMEOUT_CONN_MAX; // Set up the sockaddr structure for (size_t i = 0; i < pmmpd->malAddrList.dwAddrCount && dwRetErrorCode != NO_ERROR; i++) { // через https прокси только 443 порт if ((pmmpd->malAddrList.pMailAddress[i].dwPort == MRA_SERVER_PORT_HTTPS && bIsHTTPSProxyUsed) || bIsHTTPSProxyUsed == FALSE) { if (pmmpd->dwDataType == MRIM_PROXY_TYPE_FILES) ProtoBroadcastAck(MraHContactFromEmail(pmmpd->szEmail, FALSE, TRUE, NULL), ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)pmmpd->dwIDRequest, 0); nloc.szHost = inet_ntoa((*((in_addr*)&pmmpd->malAddrList.pMailAddress[i].dwAddr))); nloc.wPort = (WORD)pmmpd->malAddrList.pMailAddress[i].dwPort; dwCurConnectReTryCount = dwConnectReTryCount; do { pmmpd->hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)m_hNetlibUser, (LPARAM)&nloc); } while (--dwCurConnectReTryCount && pmmpd->hConnection == NULL); if (pmmpd->hConnection) { nls.cbSize = sizeof(nls); nls.dwTimeout = (MRA_TIMEOUT_DIRECT_CONN*1000*2); nls.hReadConns[0] = pmmpd->hConnection; bContinue = TRUE; dwRcvBuffSizeUsed = 0; if (pmmpd->dwDataType == MRIM_PROXY_TYPE_FILES) ProtoBroadcastAck(MraHContactFromEmail(pmmpd->szEmail, FALSE, TRUE, NULL), ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)pmmpd->dwIDRequest, 0); MraSendPacket(nls.hReadConns[0], 0, MRIM_CS_PROXY_HELLO, &pmmpd->mguidSessionID, sizeof(MRA_GUID)); while (bContinue) { switch (CallService(MS_NETLIB_SELECT, 0, (LPARAM)&nls)) { case SOCKET_ERROR: case 0:// Time out dwRetErrorCode = GetLastError(); ShowFormattedErrorMessage(L"Disconnected, socket error", dwRetErrorCode); bContinue = FALSE; break; case 1: if (dwRcvBuffSizeUsed == BUFF_SIZE_RCV_MIN_FREE) { // bad packet bContinue = FALSE; _CrtDbgBreak(); } else { dwBytesReceived = Netlib_Recv(nls.hReadConns[0], (LPSTR)(lpbBufferRcv + dwRcvBuffSizeUsed), (int)(dwRcvBuffSize - dwRcvBuffSizeUsed), 0); if (dwBytesReceived && dwBytesReceived != SOCKET_ERROR) { // connected dwRcvBuffSizeUsed += dwBytesReceived; if (dwRcvBuffSizeUsed >= sizeof(mrim_packet_header_t)) { // packet header received if (((mrim_packet_header_t*)lpbBufferRcv)->magic == CS_MAGIC) { // packet OK if ((dwRcvBuffSizeUsed-sizeof(mrim_packet_header_t)) >= ((mrim_packet_header_t*)lpbBufferRcv)->dlen) { // full packet received, may be more than one if (((mrim_packet_header_t*)lpbBufferRcv)->msg == MRIM_CS_PROXY_HELLO_ACK) // connect OK! dwRetErrorCode = NO_ERROR; else // bad/wrong _CrtDbgBreak(); bContinue = FALSE; } else // not all packet received, continue receiving debugLogA("Not all packet received, continue receiving\n"); } else { // bad packet debugLogA("Bad packet\n"); _ASSERT(false); bContinue = FALSE; } } else // packet too small, continue receiving debugLogA("Packet to small, continue receiving\n"); } else { // disconnected dwRetErrorCode = GetLastError(); ShowFormattedErrorMessage(L"Disconnected, socket read error", dwRetErrorCode); bContinue = FALSE; } } break; }// end switch }// end while } else dwRetErrorCode = GetLastError(); }// filtered }// end for if (dwRetErrorCode != NO_ERROR) // кажется не туда подключились :) NETLIB_CLOSEHANDLE(pmmpd->hConnection); } *phConnection = pmmpd->hConnection; } else dwRetErrorCode = ERROR_INVALID_HANDLE; return dwRetErrorCode; }
void CMraProto::MraAvatarsThreadProc(LPVOID lpParameter) { MRA_AVATARS_QUEUE *pmraaqAvatarsQueue = (MRA_AVATARS_QUEUE*)lpParameter; MRA_AVATARS_QUEUE_ITEM *pmraaqiAvatarsQueueItem; CMStringA szEmail, szServer; CMStringW wszFileName; BOOL bContinue, bKeepAlive, bUseKeepAliveConn, bFailed, bDownloadNew, bDefaultAvt; BYTE btBuff[BUFF_SIZE_RCV]; DWORD dwResultCode, dwAvatarFormat, dwReceived, dwServerPort, dwErrorCode; size_t dwAvatarSizeServer; FILETIME ftLastModifiedTimeServer, ftLastModifiedTimeLocal; SYSTEMTIME stAvatarLastModifiedTimeLocal; HANDLE hConnection = NULL; NETLIBSELECT nls = { 0 }; INTERNET_TIME itAvatarLastModifiedTimeServer; PROTO_AVATAR_INFORMATIONT pai; WCHAR szErrorText[2048]; nls.cbSize = sizeof(nls); pai.cbSize = sizeof(pai); InterlockedIncrement((volatile LONG*)&pmraaqAvatarsQueue->lThreadsRunningCount); while (InterlockedExchangeAdd((volatile LONG*)&pmraaqAvatarsQueue->bIsRunning, 0)) { if (FifoMTItemPop(pmraaqAvatarsQueue, NULL, (LPVOID*)&pmraaqiAvatarsQueueItem) != NO_ERROR) { // waiting until service stop or new task NETLIB_CLOSEHANDLE(hConnection); WaitForSingleObjectEx(pmraaqAvatarsQueue->hThreadEvent, MRA_AVT_DEFAULT_QE_CHK_INTERVAL, FALSE); continue; } /* Try download. */ bFailed = TRUE; bDownloadNew = FALSE; bDefaultAvt = FALSE; if (!DB_GetStringA(NULL, MRA_AVT_SECT_NAME, "Server", szServer)) szServer = MRA_AVT_DEFAULT_SERVER; dwServerPort = db_get_dw(NULL, MRA_AVT_SECT_NAME, "ServerPort", MRA_AVT_DEFAULT_SERVER_PORT); bUseKeepAliveConn = db_get_b(NULL, MRA_AVT_SECT_NAME, "UseKeepAliveConn", MRA_AVT_DEFAULT_USE_KEEPALIVE_CONN); if (mraGetStringA(pmraaqiAvatarsQueueItem->hContact, "e-mail", szEmail)) { szEmail.MakeLower(); int iStart = 0; CMStringA szUser = szEmail.Tokenize("@", iStart); CMStringA szDomain = szEmail.Tokenize("@", iStart); if (!szUser.IsEmpty() && !szDomain.IsEmpty()) { ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_CONNECTING, NULL, 0); if (hConnection == NULL) hConnection = MraAvatarsHttpConnect(pmraaqAvatarsQueue->hNetlibUser, szServer, dwServerPort); if (hConnection) { ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_CONNECTED, NULL, 0); ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_SENTREQUEST, NULL, 0); if (!MraAvatarsHttpTransaction(hConnection, REQUEST_HEAD, szUser, szDomain, szServer, MAHTRO_AVTMRIM, bUseKeepAliveConn, &dwResultCode, &bKeepAlive, &dwAvatarFormat, &dwAvatarSizeServer, &itAvatarLastModifiedTimeServer)) { switch (dwResultCode) { case 200: if (MraAvatarsGetContactTime(pmraaqiAvatarsQueueItem->hContact, "AvatarLastModifiedTime", &stAvatarLastModifiedTimeLocal)) { SystemTimeToFileTime(&itAvatarLastModifiedTimeServer.stTime, &ftLastModifiedTimeServer); SystemTimeToFileTime(&stAvatarLastModifiedTimeLocal, &ftLastModifiedTimeLocal); if ((*((DWORDLONG*)&ftLastModifiedTimeServer)) != (*((DWORDLONG*)&ftLastModifiedTimeLocal))) {// need check for update bDownloadNew = TRUE; //ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, 0, 0); } else {// avatar is valid if (MraAvatarsGetFileName(pmraaqAvatarsQueue, pmraaqiAvatarsQueueItem->hContact, dwAvatarFormat, wszFileName) == NO_ERROR) { if (IsFileExist(wszFileName)) bFailed = FALSE; else bDownloadNew = TRUE; } } } else // need update bDownloadNew = TRUE; break; case 404:// return def avatar if (MraAvatarsGetFileName((HANDLE)pmraaqAvatarsQueue, NULL, PA_FORMAT_DEFAULT, wszFileName) == NO_ERROR) { if (IsFileExist(wszFileName)) { dwAvatarFormat = ProtoGetAvatarFormat(wszFileName); bFailed = FALSE; } else//loading default avatar bDownloadNew = TRUE; bDefaultAvt = TRUE; } break; default: mir_sntprintf(szErrorText, SIZEOF(szErrorText), TranslateT("Avatars: server return HTTP code: %lu"), dwResultCode); ShowFormattedErrorMessage(szErrorText, NO_ERROR); break; } } if (bUseKeepAliveConn == FALSE || bKeepAlive == FALSE) NETLIB_CLOSEHANDLE(hConnection); } if (bDownloadNew) { if (hConnection == NULL) hConnection = MraAvatarsHttpConnect(pmraaqAvatarsQueue->hNetlibUser, szServer, dwServerPort); if (hConnection) { ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_DATA, NULL, 0); if (MraAvatarsHttpTransaction(hConnection, REQUEST_GET, szUser, szDomain, szServer, MAHTRO_AVT, bUseKeepAliveConn, &dwResultCode, &bKeepAlive, &dwAvatarFormat, &dwAvatarSizeServer, &itAvatarLastModifiedTimeServer) == NO_ERROR && dwResultCode == 200) { if (bDefaultAvt) dwAvatarFormat = PA_FORMAT_DEFAULT; if (!MraAvatarsGetFileName(pmraaqAvatarsQueue, pmraaqiAvatarsQueueItem->hContact, dwAvatarFormat, wszFileName)) { HANDLE hFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { DWORD dwWritten = 0; bContinue = TRUE; nls.dwTimeout = (1000 * db_get_dw(NULL, MRA_AVT_SECT_NAME, "TimeOutReceive", MRA_AVT_DEFAULT_TIMEOUT_RECV)); nls.hReadConns[0] = hConnection; while (bContinue) { switch (CallService(MS_NETLIB_SELECT, 0, (LPARAM)&nls)) { case SOCKET_ERROR: case 0:// Time out dwErrorCode = GetLastError(); ShowFormattedErrorMessage(L"Avatars: error on receive file data", dwErrorCode); bContinue = FALSE; break; case 1: dwReceived = Netlib_Recv(hConnection, (LPSTR)&btBuff, SIZEOF(btBuff), 0); if (dwReceived == 0 || dwReceived == SOCKET_ERROR) { dwErrorCode = GetLastError(); ShowFormattedErrorMessage(L"Avatars: error on receive file data", dwErrorCode); bContinue = FALSE; } else { if (WriteFile(hFile, (LPVOID)&btBuff, dwReceived, &dwReceived, NULL)) { dwWritten += dwReceived; if (dwWritten >= dwAvatarSizeServer) bContinue = FALSE; } else { dwErrorCode = GetLastError(); ShowFormattedErrorMessage(L"Avatars: cant write file data, error", dwErrorCode); bContinue = FALSE; } } break; } } CloseHandle(hFile); bFailed = FALSE; } else { dwErrorCode = GetLastError(); mir_sntprintf(szErrorText, SIZEOF(szErrorText), TranslateT("Avatars: can't open file %s, error"), wszFileName); ShowFormattedErrorMessage(szErrorText, dwErrorCode); } } } else _CrtDbgBreak(); if (bUseKeepAliveConn == FALSE || bKeepAlive == FALSE) NETLIB_CLOSEHANDLE(hConnection); } } } } if (bFailed) { DeleteFile(wszFileName); pai.hContact = pmraaqiAvatarsQueueItem->hContact; pai.format = PA_FORMAT_UNKNOWN; pai.filename[0] = 0; ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE)&pai, 0); } else { pai.hContact = pmraaqiAvatarsQueueItem->hContact; pai.format = dwAvatarFormat; if (db_get_b(NULL, MRA_AVT_SECT_NAME, "ReturnAbsolutePath", MRA_AVT_DEFAULT_RET_ABC_PATH)) lstrcpyn(pai.filename, wszFileName, SIZEOF(pai.filename)); else PathToRelativeT(wszFileName, pai.filename); if (bDefaultAvt) dwAvatarFormat = PA_FORMAT_DEFAULT; SetContactAvatarFormat(pmraaqiAvatarsQueueItem->hContact, dwAvatarFormat); MraAvatarsSetContactTime(pmraaqiAvatarsQueueItem->hContact, "AvatarLastModifiedTime", &itAvatarLastModifiedTimeServer.stTime); // write owner avatar file name to DB if (pmraaqiAvatarsQueueItem->hContact == NULL) // proto avatar CallService(MS_AV_REPORTMYAVATARCHANGED, (WPARAM)m_szModuleName, 0); ProtoBroadcastAck(pmraaqiAvatarsQueueItem->hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0); } mir_free(pmraaqiAvatarsQueueItem); } InterlockedDecrement((volatile LONG*)&pmraaqAvatarsQueue->lThreadsRunningCount); }