示例#1
0
void CIcqProto::handlePrivacyRightsReply(unsigned char *pBuffer, WORD wBufferLength)
{
	if (wBufferLength >= 12)
	{
		oscar_tlv_chain* pChain = readIntoTLVChain(&pBuffer, wBufferLength, 0);
		if (pChain)
		{
			WORD wMaxVisibleContacts;
			WORD wMaxInvisibleContacts;
			WORD wMaxTemporaryVisibleContacts;

			wMaxVisibleContacts = pChain->getWord(0x0001, 1);
			wMaxInvisibleContacts = pChain->getWord(0x0002, 1);
			wMaxTemporaryVisibleContacts = pChain->getWord(0x0003, 1);

			disposeChain(&pChain);

			NetLog_Server("PRIVACY: Max visible %u, max invisible %u, max temporary visible %u items.", wMaxVisibleContacts, wMaxInvisibleContacts, wMaxTemporaryVisibleContacts);

			// Success
			return;
		}
	}

	// Failure
	NetLog_Server("Warning: Malformed SRV_PRIVACY_RIGHTS_REPLY");
}
示例#2
0
void CIcqProto::handleStatusFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
{
	switch (pSnacHeader->wSubtype) {

	case ICQ_STATS_MINREPORTINTERVAL:
		{
			WORD wInterval;
			unpackWord(&pBuffer, &wInterval);
			NetLog_Server("Server sent SNAC(x0B,x02) - SRV_SET_MINREPORTINTERVAL (Value: %u hours)", wInterval);
		}
		break;

	case ICQ_ERROR:
		{
			WORD wError;

			if (wBufferLength >= 2)
				unpackWord(&pBuffer, &wError);
			else 
				wError = 0;

			LogFamilyError(ICQ_STATS_FAMILY, wError);
			break;
		}

	default:
		NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_STATS_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
		break;
	}
}
示例#3
0
int CIcqProto::connectNewServer(serverthread_info *info)
{
    int res = 0;

    /* Get the ip and port */
    WORD wServerPort = info->wServerPort; // prepare default port
    parseServerAddress(info->newServer, &wServerPort);

    NETLIBOPENCONNECTION nloc = {0};
    nloc.flags = 0;
    nloc.szHost = info->newServer;
    nloc.wPort = wServerPort;

    if (!m_bGatewayMode)
    {
        NetLib_SafeCloseHandle(&info->hPacketRecver);
        NetLib_CloseConnection(&hServerConn, TRUE);

        NetLog_Server("Closed connection to login server");

        hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc);
        if (hServerConn && info->newServerSSL)
        {   /* Start SSL session if requested */
            if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0))
                NetLib_CloseConnection(&hServerConn, FALSE);
        }

        if (hServerConn)
        {
            /* Time to recreate the packet receiver */
            info->hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
            if (!info->hPacketRecver)
            {
                NetLog_Server("Error: Failed to create packet receiver.");
            }
            else // we need to reset receiving structs
            {
                info->bReinitRecver = 1;
                res = 1;
            }
        }
    }
    else
    {   // TODO: We should really do some checks here
        NetLog_Server("Walking in Gateway to %s", info->newServer);
        // TODO: This REQUIRES more work (most probably some kind of mid-netlib module)
        icq_httpGatewayWalkTo(hServerConn, &nloc);
        res = 1;
    }
    if (!res) SAFE_FREE((void**)&info->cookieData);

    // Free allocated memory
    // NOTE: "cookie" will get freed when we have connected to the communication server.
    SAFE_FREE(&info->newServer);

    return res;
}
示例#4
0
void CIcqProto::handleLoginReply(BYTE *buf, WORD datalen, serverthread_info *info)
{
    oscar_tlv_chain *chain = NULL;

    icq_sendCloseConnection(); // imitate icq5 behaviour

    if (!(chain = readIntoTLVChain(&buf, datalen, 0)))
    {
        NetLog_Server("Error: Missing chain on close channel");
        NetLib_CloseConnection(&hServerConn, TRUE);
        return; // Invalid data
    }

    // TLV 8 errors (signon errors?)
    WORD wError = chain->getWord(0x08, 1);
    if (wError)
    {
        handleSignonError(wError);

        // we return only if the server did not gave us cookie (possible to connect with soft error)
        if (!chain->getLength(0x06, 1))
        {
            disposeChain(&chain);
            SetCurrentStatus(ID_STATUS_OFFLINE);
            icq_serverDisconnect(FALSE);
            return; // Failure
        }
    }

    // We are in the login phase and no errors were reported.
    // Extract communication server info.
    info->newServer = chain->getString(0x05, 1);
    info->newServerSSL = chain->getNumber(0x8E, 1);
    info->cookieData = (BYTE*)chain->getString(0x06, 1);
    info->cookieDataLen = chain->getLength(0x06, 1);

    // We dont need this anymore
    disposeChain(&chain);

    if (!info->newServer || !info->cookieData)
    {
        icq_LogMessage(LOG_FATAL, LPGEN("You could not sign on because the server returned invalid data. Try again."));

        SAFE_FREE(&info->newServer);
        SAFE_FREE((void**)&info->cookieData);
        info->cookieDataLen = 0;

        SetCurrentStatus(ID_STATUS_OFFLINE);
        NetLib_CloseConnection(&hServerConn, TRUE);
        return; // Failure
    }

    NetLog_Server("Authenticated.");
    info->newServerReady = 1;

    return;
}
示例#5
0
void CIcqProto::handleBosFam(unsigned char *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
{
	switch (pSnacHeader->wSubtype) {

	case ICQ_PRIVACY_RIGHTS_REPLY: // Reply to CLI_REQBOS
		handlePrivacyRightsReply(pBuffer, wBufferLength);
		break;

	case ICQ_ERROR:
		{
			WORD wError;

			if (wBufferLength >= 2)
				unpackWord(&pBuffer, &wError);
			else 
				wError = 0;

			LogFamilyError(ICQ_BOS_FAMILY, wError);
			break;
		}

	default:
		NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_BOS_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
		break;

	}
}
示例#6
0
int CIcqProto::getContactUid(HANDLE hContact, DWORD *pdwUin, uid_str *ppszUid)
{
  DBVARIANT dbv = {DBVT_DELETED};
	int iRes = 1;

	*pdwUin = 0;
	if (ppszUid) *ppszUid[0] = '\0';

	if (!getSetting(hContact, UNIQUEIDSETTING, &dbv))
	{
		if (dbv.type == DBVT_DWORD)
		{
			*pdwUin = dbv.dVal;
			iRes = 0;
		}
		else if (dbv.type == DBVT_ASCIIZ)
		{
			if (ppszUid && m_bAimEnabled) 
			{
				strcpy(*ppszUid, dbv.pszVal);
				iRes = 0;
			}
			else
				NetLog_Server("AOL screennames not accepted");
		}
		ICQFreeVariant(&dbv);
	}
	return iRes;
}
示例#7
0
void CIcqProto::handleLocationFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader)
{
	switch (pSnacHeader->wSubtype) {

	case ICQ_LOCATION_RIGHTS_REPLY: // Reply to CLI_REQLOCATION
		NetLog_Server("Server sent SNAC(x02,x03) - SRV_LOCATION_RIGHTS_REPLY");
		break;

	case ICQ_LOCATION_USR_INFO_REPLY: // AIM user info reply
		handleLocationUserInfoReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
		break;

	case ICQ_ERROR:
		{ 
			WORD wError;
			HANDLE hCookieContact;
			cookie_fam15_data *pCookieData;


			if (wBufferLength >= 2)
				unpackWord(&pBuffer, &wError);
			else 
				wError = 0;

			if (wError == 4)
			{
				if (FindCookie(pSnacHeader->dwRef, &hCookieContact, (void**)&pCookieData) && !getContactUin(hCookieContact) && pCookieData->bRequestType == REQUESTTYPE_PROFILE)
				{
					BroadcastAck(hCookieContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);

					ReleaseCookie(pSnacHeader->dwRef);
				}
			}

			LogFamilyError(ICQ_LOCATION_FAMILY, wError);
			break;
		}

	default:
		NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LOCATION_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
		break;
	}
}
示例#8
0
void CIcqProto::handleLookupEmailReply(BYTE* buf, WORD wLen, DWORD dwCookie)
{
	ICQSEARCHRESULT sr = {0};
	oscar_tlv_chain *pChain;
	cookie_search *pCookie;

	if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
	{
		NetLog_Server("Error: Received unexpected lookup reply");
		return;
	}
	
	NetLog_Server("SNAC(0x0A,0x3): Lookup reply");

	sr.hdr.cbSize = sizeof(sr);
  sr.hdr.flags = PSR_TCHAR;
	sr.hdr.email = ansi_to_tchar(pCookie->szObject);

	// Syntax check, read chain
	if (wLen >= 4 && (pChain = readIntoTLVChain(&buf, wLen, 0)))
	{
		for (WORD i = 1; TRUE; i++)
		{ // collect the results
			char *szUid = pChain->getString(0x01, i);
			if (!szUid) break;
      sr.hdr.id = ansi_to_tchar(szUid);
			sr.hdr.nick = sr.hdr.id;
			// broadcast the result
			if (pCookie->dwMainId)
				BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)pCookie->dwMainId, (LPARAM)&sr);
			else
				BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)dwCookie, (LPARAM)&sr);
			SAFE_FREE(&sr.hdr.id);
      SAFE_FREE(&szUid);
		}
		disposeChain(&pChain);
	}
  SAFE_FREE(&sr.hdr.email);

	ReleaseLookupCookie(dwCookie, pCookie);
}
示例#9
0
void CIcqProto::handleMigration(serverthread_info *info)
{
    // Check the data that was saved when the migration was announced
    NetLog_Server("Migrating to %s", info->newServer);
    if (!info->newServer || !info->cookieData)
    {
        icq_LogMessage(LOG_FATAL, LPGEN("You have been disconnected from the ICQ network because the current server shut down."));

        SAFE_FREE(&info->newServer);
        SAFE_FREE((void**)&info->cookieData);
        info->newServerReady = 0;
        info->isMigrating = 0;
    }
}
示例#10
0
void CIcqProto::handleLookupFam(BYTE *pBuffer, WORD wBufferLength, snac_header* pSnacHeader)
{
	switch (pSnacHeader->wSubtype) {

	case ICQ_LOOKUP_EMAIL_REPLY: // AIM search reply
		handleLookupEmailReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
		break;

	case ICQ_ERROR:
		{ 
			WORD wError;
			cookie_search *pCookie;

			if (wBufferLength >= 2)
				unpackWord(&pBuffer, &wError);
			else 
				wError = 0;

			if (FindCookie(pSnacHeader->dwRef, NULL, (void**)&pCookie))
			{
				if (wError == 0x14)
					NetLog_Server("Lookup: No results");

				ReleaseLookupCookie(pSnacHeader->dwRef, pCookie);

				if (wError == 0x14) return;
			}

			LogFamilyError(ICQ_LOOKUP_FAMILY, wError);
			break;
		}

	default:
		NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LOOKUP_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
		break;
	}
}
示例#11
0
void CIcqProto::icq_LogMessage(int level, const char *szMsg)
{
	NetLog_Server("%s", szMsg);

	int displayLevel = getSettingByte(NULL, "ShowLogLevel", LOG_WARNING);
	if (level >= displayLevel)
	{
		if (!bErrorBoxVisible || !getSettingByte(NULL, "IgnoreMultiErrorBox", 0))
		{ 
			// error not shown or allowed multi - show messagebox
			LogMessageInfo *lmi = (LogMessageInfo*)SAFE_MALLOC(sizeof(LogMessageInfo));
			lmi->bLevel = (BYTE)level;
			lmi->szMsg = null_strdup(szMsg);
			lmi->szTitle = szLevelDescr[level];
			ForkThread( &CIcqProto::icq_LogMessageThread, lmi);
		}
	}
}
示例#12
0
void CIcqProto::icq_serverDisconnect(BOOL bBlock)
{
	if (hServerConn)
	{
		NetLog_Server("Server shutdown requested");
		Netlib_Shutdown(hServerConn);

		if (serverThreadHandle)
		{
			// Not called from network thread?
			if (bBlock && GetCurrentThreadId() != serverThreadId)
				while (ICQWaitForSingleObject(serverThreadHandle, INFINITE) != WAIT_OBJECT_0);

			CloseHandle(serverThreadHandle);
			serverThreadHandle = NULL;
		}
	}
}
示例#13
0
void CIcqProto::makeContactTemporaryVisible(HANDLE hContact)
{
	DWORD dwUin;
	uid_str szUid;

	if (getSettingByte(hContact, "TemporaryVisible", 0))
		return; // already there

	if (getContactUid(hContact, &dwUin, &szUid))
		return; // Invalid contact

	icq_sendGenericContact(dwUin, szUid, ICQ_BOS_FAMILY, ICQ_CLI_ADDTEMPVISIBLE);

	setSettingByte(hContact, "TemporaryVisible", 1);

#ifdef _DEBUG
	NetLog_Server("Added contact %s to temporary visible list", strUID(dwUin, szUid));
#endif
}
示例#14
0
void CIcqProto::handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie)
{
	HANDLE hContact;
	DWORD dwUIN;
	uid_str szUID;
	WORD wTLVCount;
	WORD wWarningLevel;
	HANDLE hCookieContact;
	WORD status;
	cookie_message_data *pCookieData;

	// Unpack the sender's user ID
	if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;

	// Syntax check
	if (wLen < 4)
		return;

	// Warning level?
	unpackWord(&buf, &wWarningLevel);
	wLen -= 2;

	// TLV count
	unpackWord(&buf, &wTLVCount);
	wLen -= 2;

	// Determine contact
	hContact = HContactFromUID(dwUIN, szUID, NULL);

	// Ignore away status if the user is not already on our list
	if (hContact == INVALID_HANDLE_VALUE)
	{
#ifdef _DEBUG
		NetLog_Server("Ignoring away reply (%s)", strUID(dwUIN, szUID));
#endif
		return;
	}

	if (!FindCookie(dwCookie, &hCookieContact, (void**)&pCookieData))
	{
		NetLog_Server("Error: Received unexpected away reply from %s", strUID(dwUIN, szUID));
		return;
	}

	if (hContact != hCookieContact)
	{
		NetLog_Server("Error: Away reply Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);

		ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
		return;
	}

	switch (GetCookieType(dwCookie))
	{
	case CKT_FAMILYSPECIAL:
		{
			ReleaseCookie(dwCookie);

			// Read user info TLVs
			{
				oscar_tlv_chain* pChain;
				BYTE *tmp;
				char *szMsg = NULL;

				// Syntax check
				if (wLen < 4)
					return;

				tmp = buf;
				// Get general chain
				if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
					return;

				disposeChain(&pChain);

				wLen -= (buf - tmp);

				// Get extra chain
				if (pChain = readIntoTLVChain(&buf, wLen, 2))
				{
					oscar_tlv *pTLV;
					char *szEncoding = NULL;

					// Get Profile encoding TLV
					pTLV = pChain->getTLV(0x01, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szEncoding = (char*)_alloca(pTLV->wLen + 1);
						memcpy(szEncoding, pTLV->pData, pTLV->wLen);
						szEncoding[pTLV->wLen] = '\0';
					}
					// Get Profile info TLV
					pTLV = pChain->getTLV(0x02, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
						memcpy(szMsg, pTLV->pData, pTLV->wLen);
						szMsg[pTLV->wLen] = '\0';
						szMsg[pTLV->wLen + 1] = '\0';
						szMsg = AimApplyEncoding(szMsg, szEncoding);
						szMsg = EliminateHtml(szMsg, pTLV->wLen);
					}
					// Free TLV chain
					disposeChain(&pChain);
				}

				setSettingString(hContact, "About", szMsg);
				BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);

				SAFE_FREE((void**)&szMsg);
			}
			break;
		}

	default: // away message
		{
			status = AwayMsgTypeToStatus(pCookieData->nAckType);
			if (status == ID_STATUS_OFFLINE)
			{
				NetLog_Server("SNAC(2.6) Ignoring unknown status message from %s", strUID(dwUIN, szUID));

				ReleaseCookie(dwCookie);
				return;
			}

			ReleaseCookie(dwCookie);

			// Read user info TLVs
			{
				oscar_tlv_chain* pChain;
				oscar_tlv* pTLV;
				BYTE *tmp;
				char *szMsg = NULL;
				CCSDATA ccs;
				PROTORECVEVENT pre;

				// Syntax check
				if (wLen < 4)
					return;

				tmp = buf;
				// Get general chain
				if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
					return;

				disposeChain(&pChain);

				wLen -= (buf - tmp);

				// Get extra chain
				if (pChain = readIntoTLVChain(&buf, wLen, 2))
				{
					char* szEncoding = NULL;

					// Get Away encoding TLV
					pTLV = pChain->getTLV(0x03, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szEncoding = (char*)_alloca(pTLV->wLen + 1);
						memcpy(szEncoding, pTLV->pData, pTLV->wLen);
						szEncoding[pTLV->wLen] = '\0';
					}
					// Get Away info TLV
					pTLV = pChain->getTLV(0x04, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
						memcpy(szMsg, pTLV->pData, pTLV->wLen);
						szMsg[pTLV->wLen] = '\0';
						szMsg[pTLV->wLen + 1] = '\0';
						szMsg = AimApplyEncoding(szMsg, szEncoding);
						szMsg = EliminateHtml(szMsg, pTLV->wLen);
					}
					// Free TLV chain
					disposeChain(&pChain);
				}

				ccs.szProtoService = PSR_AWAYMSG;
				ccs.hContact = hContact;
				ccs.wParam = status;
				ccs.lParam = (LPARAM)&pre;
				pre.flags = 0;
				pre.szMessage = szMsg?szMsg:(char *)"";
				pre.timestamp = time(NULL);
				pre.lParam = dwCookie;

				CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);

				SAFE_FREE((void**)&szMsg);
			}
			break;
		}
	}
}
示例#15
0
int CIcqProto::handleServerPackets(BYTE *buf, int len, serverthread_info *info)
{
	BYTE channel;
	WORD sequence;
	WORD datalen;
	int bytesUsed = 0;

	while (len > 0)
	{
		if (info->bReinitRecver)
			break;

		// All FLAPS begin with 0x2a
		if (*buf++ != FLAP_MARKER)
			break;

		if (len < 6)
			break;

		unpackByte(&buf, &channel);
		unpackWord(&buf, &sequence);
		unpackWord(&buf, &datalen);

		if (len < 6 + datalen)
			break;


#ifdef _DEBUG
		NetLog_Server("Server FLAP: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
#endif

		switch (channel) {
		case ICQ_LOGIN_CHAN:
			handleLoginChannel(buf, datalen, info);
			break;

		case ICQ_DATA_CHAN:
			handleDataChannel(buf, datalen, info);
			break;

		case ICQ_ERROR_CHAN:
			handleErrorChannel(buf, datalen);
			break;

		case ICQ_CLOSE_CHAN:
			handleCloseChannel(buf, datalen, info);
			break; // we need this for walking thru proxy

		case ICQ_PING_CHAN:
			handlePingChannel(buf, datalen);
			break;

		default:
			NetLog_Server("Warning: Unhandled Server FLAP Channel: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
			break;
		}

		/* Increase pointers so we can check for more FLAPs */
		buf += datalen;
		len -= (datalen + 6);
		bytesUsed += (datalen + 6);
	}

	return bytesUsed;
}
示例#16
0
void __cdecl CIcqProto::ServerThread(serverthread_start_info *infoParam)
{
	serverthread_info info = {0};

	info.isLoginServer = 1;
	info.wAuthKeyLen = infoParam->wPassLen;
	null_strcpy((char*)info.szAuthKey, infoParam->szPass, info.wAuthKeyLen);
	// store server port
	info.wServerPort = infoParam->nloc.wPort;

	srand(time(NULL));

	ResetSettingsOnConnect();

	// Connect to the login server
	NetLog_Server("Authenticating to server");
	{
		NETLIBOPENCONNECTION nloc = infoParam->nloc;
		nloc.timeout = 6;
		if (m_bGatewayMode)
			nloc.flags |= NLOCF_HTTPGATEWAY;

		hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc);

		SAFE_FREE((void**)&nloc.szHost);
		SAFE_FREE((void**)&infoParam);

		if (hServerConn && m_bSecureConnection)
		{
			if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0))
			{
				icq_LogMessage(LOG_ERROR, LPGEN("Unable to connect to ICQ login server, SSL could not be negotiated"));
				SetCurrentStatus(ID_STATUS_OFFLINE);
				NetLib_CloseConnection(&hServerConn, TRUE);
				return;
			}
		}

	}

	// Login error
	if (hServerConn == NULL)
	{
		DWORD dwError = GetLastError();

		SetCurrentStatus(ID_STATUS_OFFLINE);

		icq_LogUsingErrorCode(LOG_ERROR, dwError, LPGEN("Unable to connect to ICQ login server"));
		return;
	}

	// Initialize direct connection ports
	{
		DWORD dwInternalIP;
		BYTE bConstInternalIP = getSettingByte(NULL, "ConstRealIP", 0);

		info.hDirectBoundPort = NetLib_BindPort(icq_newConnectionReceived, this, &wListenPort, &dwInternalIP);
		if (!info.hDirectBoundPort)
		{
			icq_LogUsingErrorCode(LOG_WARNING, GetLastError(), LPGEN("Miranda was unable to allocate a port to listen for direct peer-to-peer connections between clients. You will be able to use most of the ICQ network without problems but you may be unable to send or receive files.\n\nIf you have a firewall this may be blocking Miranda, in which case you should configure your firewall to leave some ports open and tell Miranda which ports to use in M->Options->ICQ->Network."));
			wListenPort = 0;
			if (!bConstInternalIP) deleteSetting(NULL, "RealIP");
		}
		else if (!bConstInternalIP)
			setSettingDword(NULL, "RealIP", dwInternalIP);
	}

	// Initialize rate limiting queues
	{ 
		icq_lock l(m_ratesMutex);

		m_ratesQueue_Request = new rates_queue(this, "request", RML_IDLE_30, RML_IDLE_50, 1);
		m_ratesQueue_Response = new rates_queue(this, "response", RML_IDLE_10, RML_IDLE_30, -1);
	}

	// This is the "infinite" loop that receives the packets from the ICQ server
	{
		int recvResult;
		NETLIBPACKETRECVER packetRecv = {0};

		info.hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
		packetRecv.cbSize = sizeof(packetRecv);
		packetRecv.dwTimeout = INFINITE;
		while (serverThreadHandle)
		{
			if (info.bReinitRecver)
			{ // we reconnected, reinit struct
				info.bReinitRecver = 0;
				ZeroMemory(&packetRecv, sizeof(packetRecv));
				packetRecv.cbSize = sizeof(packetRecv);
				packetRecv.dwTimeout = INFINITE;
			}

			recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)info.hPacketRecver, (LPARAM)&packetRecv);

			if (recvResult == 0)
			{
				NetLog_Server("Clean closure of server socket");
				break;
			}

			if (recvResult == SOCKET_ERROR)
			{
				NetLog_Server("Abortive closure of server socket, error: %d", GetLastError());
				break;
			}

			if (m_iDesiredStatus == ID_STATUS_OFFLINE)
			{ // Disconnect requested, send disconnect packet
				icq_sendCloseConnection();

				// disconnected upon request
				m_bConnectionLost = FALSE;
				SetCurrentStatus(ID_STATUS_OFFLINE);

				NetLog_Server("Logged off.");
				break;
			}

			// Deal with the packet
			packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable, &info);
		}
		serverThreadHandle = NULL;

		// Time to shutdown
		NetLib_CloseConnection(&hServerConn, TRUE);

		// Close the packet receiver (connection may still be open)
		NetLib_SafeCloseHandle(&info.hPacketRecver);

		// Close DC port
		NetLib_SafeCloseHandle(&info.hDirectBoundPort);
	}

	// disable auto info-update thread
	icq_EnableUserLookup(FALSE);

	if (m_iStatus != ID_STATUS_OFFLINE && m_iDesiredStatus != ID_STATUS_OFFLINE)
	{
		if (!info.bLoggedIn)
			icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nLogin sequence failed for unknown reason.\nTry again later."));

		// set flag indicating we were kicked out
		m_bConnectionLost = TRUE;

		SetCurrentStatus(ID_STATUS_OFFLINE);
	}

	// signal keep-alive thread to stop
	StopKeepAlive(&info);

	// Close all open DC connections
	CloseContactDirectConns(NULL);

	// Close avatar connection if any
	StopAvatarThread();

	// Offline all contacts
	HANDLE hContact = FindFirstContact();
	while (hContact)
	{
		DWORD dwUIN;
		uid_str szUID;

		if (!getContactUid(hContact, &dwUIN, &szUID))
		{
			if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
			{
				char tmp = 0;

				setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);

				handleXStatusCaps(dwUIN, szUID, hContact, (BYTE*)&tmp, 0, &tmp, 0);
			}
		}

		hContact = FindNextContact(hContact);
	}

	setSettingDword(NULL, "LogonTS", 0); // clear logon time

	servlistPendingFlushOperations(); // clear pending operations list

	{ // release rates queues
		icq_lock l(m_ratesMutex);

		SAFE_DELETE((void_struct**)&m_ratesQueue_Request);
		SAFE_DELETE((void_struct**)&m_ratesQueue_Response);
		SAFE_DELETE((void_struct**)&m_rates);
	}

	FlushServerIDs();         // clear server IDs list

	NetLog_Server("%s thread ended.", "Server");
}
示例#17
0
void CIcqProto::handleLoginChannel(BYTE *buf, WORD datalen, serverthread_info *info)
{
	icq_packet packet;

#ifdef _DEBUG
  NetLog_Server("Received SRV_HELLO from %s", info->isLoginServer ? "login server" : "communication server");
#endif

	// isLoginServer is "1" if we just received SRV_HELLO
	if (info->isLoginServer)
	{
		if (m_bSecureLogin)
		{
			char szUin[UINMAXLEN];
			WORD wUinLen;

#ifdef _DEBUG
			NetLog_Server("Sending %s to %s", "CLI_HELLO", "login server");
#endif
			packet.wLen = 12;
			write_flap(&packet, ICQ_LOGIN_CHAN);
			packDWord(&packet, 0x00000001);
			packTLVDWord(&packet, 0x8003, 0x00100000); // unknown
			sendServPacket(&packet);  // greet login server

			wUinLen = strlennull(strUID(m_dwLocalUIN, szUin));
#ifdef _DEBUG
			NetLog_Server("Sending %s to %s", "ICQ_SIGNON_AUTH_REQUEST", "login server");
#endif

			serverPacketInit(&packet, (WORD)(14 + wUinLen));
			packFNACHeader(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_AUTH_REQUEST, 0, 0);
			packTLV(&packet, 0x0001, wUinLen, (LPBYTE)szUin);
			sendServPacket(&packet);  // request login digest
		}
		else
		{
			sendClientAuth((char*)info->szAuthKey, info->wAuthKeyLen, FALSE);
#ifdef _DEBUG
			NetLog_Server("Sent CLI_IDENT to %s", "login server");
#endif
		}

		info->isLoginServer = 0;
		if (info->cookieDataLen)
		{
			SAFE_FREE((void**)&info->cookieData);
			info->cookieDataLen = 0;
		}
	}
	else 
	{
		if (info->cookieDataLen)
		{
			wLocalSequence = generate_flap_sequence();

			serverCookieInit(&packet, info->cookieData, (WORD)info->cookieDataLen);
			sendServPacket(&packet);

#ifdef _DEBUG
			NetLog_Server("Sent CLI_IDENT to %s", "communication server");
#endif

			SAFE_FREE((void**)&info->cookieData);
			info->cookieDataLen = 0;
		}
		else
		{
			// We need a cookie to identify us to the communication server
      NetLog_Server("Error: Connected to %s without a cookie!", "communication server");
		}
	}
}