Beispiel #1
0
void MraMrimProxyCloseConnection(HANDLE hMraMrimProxyData)
{
	if (hMraMrimProxyData) {
		MRA_MRIMPROXY_DATA *pmmpd = (MRA_MRIMPROXY_DATA*)hMraMrimProxyData;
		SetEvent(pmmpd->hWaitHandle);
		NETLIB_CLOSEHANDLE(pmmpd->hConnection);
	}
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}
Beispiel #4
0
int CMraProto::SetStatus(int iNewStatus)
{
    // remap global statuses to local supported
    switch (iNewStatus) {
    case ID_STATUS_OCCUPIED:
        iNewStatus = ID_STATUS_DND;
        break;
    case ID_STATUS_NA:
    case ID_STATUS_ONTHEPHONE:
    case ID_STATUS_OUTTOLUNCH:
        iNewStatus = ID_STATUS_AWAY;
        break;
    }

    // nothing to change
    if (m_iStatus == iNewStatus)
        return 0;

    DWORD dwOldStatusMode;

    //set all contacts to offline
    if ((m_iDesiredStatus = iNewStatus) == ID_STATUS_OFFLINE) {
        m_bLoggedIn = FALSE;
        dwOldStatusMode = InterlockedExchange((volatile LONG*)&m_iStatus, m_iDesiredStatus);

        // всех в offline, только если мы бывали подключены
        if (dwOldStatusMode > ID_STATUS_OFFLINE)
            for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName))
                SetContactBasicInfoW(hContact, SCBIFSI_LOCK_CHANGES_EVENTS, (SCBIF_ID | SCBIF_GROUP_ID | SCBIF_SERVER_FLAG | SCBIF_STATUS), -1, -1, 0, 0, ID_STATUS_OFFLINE, 0, 0, 0);

        NETLIB_CLOSEHANDLE(m_hConnection);
    }
    else {
        // если offline то сразу ставим connecting, но обработка как offline
        dwOldStatusMode = InterlockedCompareExchange((volatile LONG*)&m_iStatus, ID_STATUS_CONNECTING, ID_STATUS_OFFLINE);

        switch (dwOldStatusMode) {
        case ID_STATUS_OFFLINE: // offline, connecting
            if (StartConnect() != NO_ERROR) {
                m_bLoggedIn = FALSE;
                m_iDesiredStatus = ID_STATUS_OFFLINE;
                dwOldStatusMode = InterlockedExchange((volatile LONG*)&m_iStatus, m_iDesiredStatus);
            }
            break;
        case ID_STATUS_ONLINE:// connected, change status
        case ID_STATUS_AWAY:
        case ID_STATUS_DND:
        case ID_STATUS_FREECHAT:
        case ID_STATUS_INVISIBLE:
            MraSendNewStatus(m_iDesiredStatus, m_iXStatus, _T(""), _T(""));
        case ID_STATUS_CONNECTING:
            // предотвращаем переход в любой статус (кроме offline) из статуса connecting, если он не вызван самим плагином
            if (dwOldStatusMode == ID_STATUS_CONNECTING && iNewStatus != m_iDesiredStatus)
                break;

        default:
            dwOldStatusMode = InterlockedExchange((volatile LONG*)&m_iStatus, m_iDesiredStatus);
            break;
        }
    }
    MraSetContactStatus(NULL, m_iStatus);
    ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)dwOldStatusMode, m_iStatus);
    return 0;
}