⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clientlist.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
void CClientList::AddTrackClient(CUpDownClient* toadd){
	CDeletedClient* pResult = 0;
	if (m_trackedClientsList.Lookup(toadd->GetIP(), pResult)){
		pResult->m_dwInserted = ::GetTickCount();
		for (int i = 0; i != pResult->m_ItemsList.GetCount(); i++){
			if (pResult->m_ItemsList[i].nPort == toadd->GetUserPort()){
				// already tracked, update
				pResult->m_ItemsList[i].pHash = toadd->Credits();
				return;
			}
		}
		PORTANDHASH porthash = { toadd->GetUserPort(), toadd->Credits()};
		pResult->m_ItemsList.Add(porthash);
	}
	else{
		m_trackedClientsList.SetAt(toadd->GetIP(), new CDeletedClient(toadd));
	}
}

// true = everything ok, hash didn't changed
// false = hash changed
bool CClientList::ComparePriorUserhash(uint32 dwIP, uint16 nPort, void* pNewHash){
	CDeletedClient* pResult = 0;
	if (m_trackedClientsList.Lookup(dwIP, pResult)){
		for (int i = 0; i != pResult->m_ItemsList.GetCount(); i++){
			if (pResult->m_ItemsList[i].nPort == nPort){
				if (pResult->m_ItemsList[i].pHash != pNewHash)
					return false;
				else
					break;
			}
		}
	}
	return true;
}

UINT CClientList::GetClientsFromIP(uint32 dwIP) const
{
	CDeletedClient* pResult;
	if (m_trackedClientsList.Lookup(dwIP, pResult))
		return pResult->m_ItemsList.GetCount();
	return 0;
}

void CClientList::TrackBadRequest(const CUpDownClient* upcClient, sint32 nIncreaseCounter){
	CDeletedClient* pResult = NULL;
	if (upcClient->GetIP() == 0){
		ASSERT( false );
		return;
	}
	if (m_trackedClientsList.Lookup(upcClient->GetIP(), pResult)){
		pResult->m_dwInserted = ::GetTickCount();
		pResult->m_cBadRequest += nIncreaseCounter;
	}
	else{
		CDeletedClient* ccToAdd = new CDeletedClient(upcClient);
		ccToAdd->m_cBadRequest = nIncreaseCounter;
		m_trackedClientsList.SetAt(upcClient->GetIP(), ccToAdd);
	}
}

uint32 CClientList::GetBadRequests(const CUpDownClient* upcClient) const{
	CDeletedClient* pResult = NULL;
	if (upcClient->GetIP() == 0){
		ASSERT( false );
		return 0;
	}
	if (m_trackedClientsList.Lookup(upcClient->GetIP(), pResult)){
		return pResult->m_cBadRequest;
	}
	else
		return 0;
}

void CClientList::Process(){
	const uint32 cur_tick = ::GetTickCount();
	if (m_dwLastBannCleanUp + BAN_CLEANUP_TIME < cur_tick){
		m_dwLastBannCleanUp = cur_tick;
		
		POSITION pos = m_bannedList.GetStartPosition();
		uint32 nKey;
		uint32 dwBantime;
		while (pos != NULL){
			m_bannedList.GetNextAssoc( pos, nKey, dwBantime );
			if (dwBantime + CLIENTBANTIME < cur_tick )
				RemoveBannedClient(nKey);
		}
	}

	
	if (m_dwLastTrackedCleanUp + TRACKED_CLEANUP_TIME < cur_tick ){
		m_dwLastTrackedCleanUp = cur_tick;
		if (thePrefs.GetLogBannedClients())
			AddDebugLogLine(false, _T("Cleaning up TrackedClientList, %i clients on List..."), m_trackedClientsList.GetCount());
		POSITION pos = m_trackedClientsList.GetStartPosition();
		uint32 nKey;
		CDeletedClient* pResult;
		while (pos != NULL){
			m_trackedClientsList.GetNextAssoc( pos, nKey, pResult );
			if (pResult->m_dwInserted + KEEPTRACK_TIME < cur_tick ){
				m_trackedClientsList.RemoveKey(nKey);
				delete pResult;
			}
		}
		if (thePrefs.GetLogBannedClients())
			AddDebugLogLine(false, _T("...done, %i clients left on list"), m_trackedClientsList.GetCount());
	}

	//We need to try to connect to the clients in KadList
	//If connected, remove them from the list and send a message back to Kad so we can send a ACK.
	//If we don't connect, we need to remove the client..
	//The sockets timeout should delete this object.
	POSITION pos1, pos2;
	bool buddy = false;
	for (pos1 = KadList.GetHeadPosition();( pos2 = pos1 ) != NULL;)
	{
		KadList.GetNext(pos1);
		CUpDownClient* cur_client =	KadList.GetAt(pos2);
		if( !Kademlia::CKademlia::getUDPListener() )
		{
			//Clear out this list if we stop running Kad.
			cur_client->SetKadState(KS_NONE);
		}
		switch(cur_client->GetKadState())
		{
			case KS_QUEUED_FWCHECK:
				//I removed the self check here because we already did it when we added the client object.
				cur_client->TryToConnect(true);
				break;

			case KS_CONNECTING_FWCHECK:
				//Ignore this state as we are just waiting for results.
				break;

			case KS_CONNECTED_FWCHECK:
				//Send the Kademlia client a TCP connection ack!
				Kademlia::CKademlia::getUDPListener()->sendNullPacket(KADEMLIA_FIREWALLED_ACK, ntohl(cur_client->GetIP()), cur_client->GetKadPort());
				cur_client->SetKadState(KS_NONE);
				break;
			case KS_INCOMING_BUDDY:
				if( m_bHaveBuddy == 2)
					cur_client->SetKadState(KS_NONE);
				break;
			case KS_QUEUED_BUDDY:
				if( m_bHaveBuddy == 0 )
				{
					buddy = true;
					m_bHaveBuddy = 1;
					cur_client->SetKadState(KS_CONNECTING_BUDDY);
					cur_client->TryToConnect(true);
					theApp.emuledlg->serverwnd->UpdateMyInfo();
				}
				else if( m_bHaveBuddy == 2 )
					cur_client->SetKadState(KS_NONE);
				//a potential buddy client wanting to let me in the Kad network
				break;
			case KS_CONNECTING_BUDDY:
				if( m_bHaveBuddy == 2 )
					cur_client->SetKadState(KS_NONE);
				else
					buddy = true;
				break;
			case KS_CONNECTED_BUDDY:
				//a potential connected buddy client wanting to me in the Kad network
				//Not working at the moment so just set to none..
				buddy = true;
				if( m_bHaveBuddy != 2 )
				{
					m_pBuddy = cur_client;
					m_bHaveBuddy = 2;
					theApp.emuledlg->serverwnd->UpdateMyInfo();
				}
				break;
			default:
				RemoveFromKadList(cur_client);
		}
	}
	
	//We either never had a buddy, or lost our buddy..
	if( !buddy )
	{
		if( m_bHaveBuddy )
		{
			m_bHaveBuddy = 0;
			theApp.emuledlg->serverwnd->UpdateMyInfo();
		}
	}

	//Check if we are a lowID and need a buddy..
	if ( !m_bHaveBuddy && Kademlia::CKademlia::isConnected() && Kademlia::CKademlia::isFirewalled() )
	{
		ASSERT( Kademlia::CKademlia::getPrefs() != NULL );
		if( Kademlia::CKademlia::getPrefs()->getFindBuddy() )
		{
			Kademlia::CSearch *findBuddy = new Kademlia::CSearch;
			findBuddy->setSearchTypes(Kademlia::CSearch::FINDBUDDY);
			Kademlia::CUInt128 ID(true);
			ID.xor(Kademlia::CKademlia::getPrefs()->getKadID());
			findBuddy->setTargetID(ID);
			Kademlia::CSearchManager::startSearch(findBuddy);
		}
	}

	CleanUpClientList();
}

#ifdef _DEBUG
void CClientList::Debug_SocketDeleted(CClientReqSocket* deleted){
	for (POSITION pos = list.GetHeadPosition(); pos != NULL;){
		CUpDownClient* cur_client =	list.GetNext(pos);
		if (!AfxIsValidAddress(cur_client, sizeof(CUpDownClient))) {
			AfxDebugBreak();
		}
		if (thePrefs.m_iDbgHeap >= 2)
			ASSERT_VALID(cur_client);
		if (cur_client->socket == deleted){
			AfxDebugBreak();
		}
	}
}
#endif

bool CClientList::IsValidClient(CUpDownClient* tocheck)
{
	if (thePrefs.m_iDbgHeap >= 2)
		ASSERT_VALID(tocheck);
	return list.Find(tocheck);
}

void CClientList::RequestTCP(Kademlia::CContact* contact)
{
	uint32 nContactIP = ntohl(contact->getIPAddress());
	// don't connect ourself
	if (theApp.serverconnect->GetLocalIP() == nContactIP && thePrefs.GetPort() == contact->getTCPPort())
		return;

	CUpDownClient* pNewClient = FindClientByIP(nContactIP, contact->getTCPPort());

	if (!pNewClient)
		pNewClient = new CUpDownClient(0, contact->getTCPPort(), contact->getIPAddress(), 0, 0, false );

	//Add client to the lists to be processed.
	pNewClient->SetKadPort(contact->getUDPPort());
	pNewClient->SetKadState(KS_QUEUED_FWCHECK);
	KadList.AddTail(pNewClient);
	//This method checks if this is a dup already.
	AddClient(pNewClient);
}

void CClientList::RequestBuddy(Kademlia::CContact* contact)
{
	uint32 nContactIP = ntohl(contact->getIPAddress());
	// don't connect ourself
	if (theApp.serverconnect->GetLocalIP() == nContactIP && thePrefs.GetPort() == contact->getTCPPort())
		return;
	CUpDownClient* pNewClient = FindClientByIP(nContactIP, contact->getTCPPort());
	if (!pNewClient)
		pNewClient = new CUpDownClient(0, contact->getTCPPort(), contact->getIPAddress(), 0, 0, false );

	//Add client to the lists to be processed.
	pNewClient->SetKadPort(contact->getUDPPort());
	pNewClient->SetKadState(KS_QUEUED_BUDDY);
	byte ID[16];
	contact->getClientID().toByteArray(ID);
	pNewClient->SetUserHash(ID);
	AddToKadList(pNewClient);
	//This method checks if this is a dup already.
	AddClient(pNewClient);
}

void CClientList::IncomingBuddy(Kademlia::CContact* contact, Kademlia::CUInt128* buddyID )
{
	uint32 nContactIP = ntohl(contact->getIPAddress());
	//If eMule already knows this client, abort this.. It could cause conflicts.
	//Although the odds of this happening is very small, it could still happen.
	if (FindClientByIP(nContactIP, contact->getTCPPort()))
	{
		return;
	}

	// don't connect ourself
	if (theApp.serverconnect->GetLocalIP() == nContactIP && thePrefs.GetPort() == contact->getTCPPort())
		return;

	//Add client to the lists to be processed.
	CUpDownClient* pNewClient = new CUpDownClient(0, contact->getTCPPort(), contact->getIPAddress(), 0, 0, false );
	pNewClient->SetKadPort(contact->getUDPPort());
	pNewClient->SetKadState(KS_INCOMING_BUDDY);
	byte ID[16];
	contact->getClientID().toByteArray(ID);
	pNewClient->SetUserHash(ID);
	buddyID->toByteArray(ID);
	pNewClient->SetBuddyID(ID);
	AddToKadList(pNewClient);
	AddClient(pNewClient);
}

void CClientList::RemoveFromKadList(CUpDownClient* torem){
	POSITION pos = KadList.Find(torem);
	if(pos)
	{
		if(torem == m_pBuddy)
		{
			m_pBuddy = NULL;
			theApp.emuledlg->serverwnd->UpdateMyInfo();
		}
		KadList.RemoveAt(pos);
	}
}

void CClientList::AddToKadList(CUpDownClient* toadd){
	if(!toadd)
		return;
	POSITION pos = KadList.Find(toadd);
	if(pos)
	{
		return;
	}
	KadList.AddTail(toadd);
}

void CClientList::CleanUpClientList(){
	// we remove clients which are not needed any more by time
	// this check is also done on CUpDownClient::Disconnected, however it will not catch all
	// cases (if a client changes the state without beeing connected
	//
	// Adding this check directly to every point where any state changes would be more effective,
	// is however not compatible with the current code, because there are points where a client has
	// no state for some code lines and the code is also not prepared that a client object gets
	// invalid while working with it (aka setting a new state)
	// so this way is just the easy and safe one to go (as long as emule is basically single threaded)
	const uint32 cur_tick = ::GetTickCount();
	if (m_dwLastClientCleanUp + CLIENTLIST_CLEANUP_TIME < cur_tick ){
		m_dwLastClientCleanUp = cur_tick;
		POSITION pos1, pos2;
		uint32 cDeleted = 0;
		for (pos1 = list.GetHeadPosition();( pos2 = pos1 ) != NULL;){
			list.GetNext(pos1);
			CUpDownClient* pCurClient =	list.GetAt(pos2);
			if ((pCurClient->GetUploadState() == US_NONE || pCurClient->GetUploadState() == US_BANNED && !pCurClient->IsBanned())
				&& pCurClient->GetDownloadState() == DS_NONE
				&& pCurClient->GetChatState() == MS_NONE
				&& pCurClient->GetKadState() == KS_NONE
				&& pCurClient->socket == NULL)
			{
				cDeleted++;
				delete pCurClient;
			}
		}
		DEBUG_ONLY(AddDebugLogLine(false,_T("Cleaned ClientList, removed %i not used known clients"), cDeleted));
	}
}


CDeletedClient::CDeletedClient(const CUpDownClient* pClient)
{
	m_cBadRequest = 0;
	m_dwInserted = ::GetTickCount();
	PORTANDHASH porthash = { pClient->GetUserPort(), pClient->Credits()};
	m_ItemsList.Add(porthash);
}

//EastShare Start - added by AndCycle, IP to Country
void CClientList::ResetIP2Country(){

	CUpDownClient *cur_client;

	for(POSITION pos = list.GetHeadPosition(); pos != NULL; list.GetNext(pos)) { 
		cur_client = theApp.clientlist->list.GetAt(pos); 
		cur_client->ResetIP2Country();
	}

}
//EastShare End - added by AndCycle, IP to Country

// ZZ:DownloadManager -->
void CClientList::ProcessA4AFClients() {
    //if(thePrefs.GetLogA4AF()) AddDebugLogLine(false, _T(">>> Starting A4AF check"));
	POSITION pos1, pos2;
	for (pos1 = list.GetHeadPosition();( pos2 = pos1 ) != NULL;){
		list.GetNext(pos1);
		CUpDownClient* cur_client =	list.GetAt(pos2);

        if(cur_client->GetDownloadState() != DS_DOWNLOADING &&
           cur_client->GetDownloadState() != DS_CONNECTED &&
           (!cur_client->m_OtherRequests_list.IsEmpty() || !cur_client->m_OtherNoNeeded_list.IsEmpty())) {
            //AddDebugLogLine(false, _T("+++ ZZ:DownloadManager: Trying for better file for source: %s '%s'"), cur_client->GetUserName(), cur_client->reqfile->GetFileName());
               cur_client->SwapToAnotherFile(_T("Periodic A4AF check CClientList::ProcessA4AFClients()"), false, false, false, NULL, true, false);
        }
	}
    //if(thePrefs.GetLogA4AF()) AddDebugLogLine(false, _T(">>> Done with A4AF check"));
}
// <-- ZZ:DownloadManager

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -