void CClientList::RemoveClient(CUpDownClient* toremove, LPCTSTR pszReason){ POSITION pos = list.Find(toremove); if (pos){ theApp.uploadqueue->RemoveFromUploadQueue(toremove, CString(_T("CClientList::RemoveClient: ")) + pszReason); theApp.uploadqueue->RemoveFromWaitingQueue(toremove); theApp.downloadqueue->RemoveSource(toremove); theApp.emuledlg->transferwnd->clientlistctrl.RemoveClient(toremove); RemoveFromKadList(toremove); list.RemoveAt(pos); } }
void CClientList::RemoveClient(CUpDownClient* client) { RemoveFromKadList( client ); RemoveDirectCallback( client ); if ( RemoveIDFromList( client ) ) { // Also remove the ip and hash entries RemoveIPFromList( client ); RemoveHashFromList( client ); } }
void CClientList::RemoveClient(CUpDownClient* toremove, LPCTSTR pszReason){ POSITION pos = list.Find(toremove); if (pos){ theApp.uploadqueue->RemoveFromUploadQueue(toremove, CString(_T("CClientList::RemoveClient: ")) + pszReason); theApp.uploadqueue->RemoveFromWaitingQueue(toremove); // EastShare START - Added by TAHO, modified SUQWT if ( toremove != NULL && toremove->Credits() != NULL) { toremove->Credits()->ClearWaitStartTime(); } // EastShare END - Added by TAHO, modified SUQWT theApp.downloadqueue->RemoveSource(toremove); theApp.emuledlg->transferwnd->GetClientList()->RemoveClient(toremove); list.RemoveAt(pos); } RemoveFromKadList(toremove); RemoveConnectingClient(toremove); }
void CClientList::RemoveClient(CUpDownClient* toremove, LPCTSTR pszReason){ POSITION pos = list.Find(toremove); if (pos){ CGlobalVariable::uploadqueue->RemoveFromUploadQueue(toremove, CString(_T("CClientList::RemoveClient: ")) + pszReason); CGlobalVariable::uploadqueue->RemoveFromWaitingQueue(toremove); CGlobalVariable::downloadqueue->RemoveSource(toremove); #if _ENABLE_NOUSE // Comment UI //SendMessage(CGlobalVariable::m_hListenWnd,WM_FILE_REMOVE_PEER,1,(LPARAM)toremove); UINotify(WM_FILE_REMOVE_PEER,1,(LPARAM)toremove, toremove, true); //theApp.emuledlg->transferwnd->clientlistctrl.RemoveClient(toremove); #endif list.RemoveAt(pos); } RemoveFromKadList(toremove); RemoveConnectingClient(toremove); }
void CClientList::Process() { /////////////////////////////////////////////////////////////////////////// // Cleanup banned client list // 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); } } /////////////////////////////////////////////////////////////////////////// // Cleanup tracked client list // 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()); } /////////////////////////////////////////////////////////////////////////// // Process Kad client list // //We need to try to connect to the clients in m_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; // buddy is just a flag that is used to make sure we are still connected or connecting to a buddy. buddyState buddy = Disconnected; for (pos1 = m_KadList.GetHeadPosition(); (pos2 = pos1) != NULL; ) { m_KadList.GetNext(pos1); CUpDownClient* cur_client = m_KadList.GetAt(pos2); if( !Kademlia::CKademlia::IsRunning() ) { //Clear out this list if we stop running Kad. //Setting the Kad state to KS_NONE causes it to be removed in the switch below. cur_client->SetKadState(KS_NONE); } switch(cur_client->GetKadState()) { case KS_QUEUED_FWCHECK: case KS_QUEUED_FWCHECK_UDP: //Another client asked us to try to connect to them to check their firewalled status. cur_client->TryToConnect(true, true); break; case KS_CONNECTING_FWCHECK: //Ignore this state as we are just waiting for results. break; case KS_FWCHECK_UDP: case KS_CONNECTING_FWCHECK_UDP: // we want a UDP firewallcheck from this client and are just waiting to get connected to send the request break; case KS_CONNECTED_FWCHECK: //We successfully connected to the client. //We now send a ack to let them know. if (cur_client->GetKadVersion() >= KADEMLIA_VERSION7_49a){ // the result is now sent per TCP instead of UDP, because this will fail if our intern UDP port is unreachable. // But we want the TCP testresult regardless if UDP is firewalled, the new UDP state and test takes care of the rest ASSERT( cur_client->socket != NULL && cur_client->socket->IsConnected() ); if (thePrefs.GetDebugClientTCPLevel() > 0) DebugSend("OP_KAD_FWTCPCHECK_ACK", cur_client); Packet* pPacket = new Packet(OP_KAD_FWTCPCHECK_ACK, 0, OP_EMULEPROT); if (!cur_client->SafeConnectAndSendPacket(pPacket)) cur_client = NULL; } else { if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA_FIREWALLED_ACK_RES", cur_client->GetIP(), cur_client->GetKadPort()); Kademlia::CKademlia::GetUDPListener()->SendNullPacket(KADEMLIA_FIREWALLED_ACK_RES, ntohl(cur_client->GetIP()), cur_client->GetKadPort(), 0, NULL); } //We are done with this client. Set Kad status to KS_NONE and it will be removed in the next cycle. if (cur_client != NULL) cur_client->SetKadState(KS_NONE); break; case KS_INCOMING_BUDDY: //A firewalled client wants us to be his buddy. //If we already have a buddy, we set Kad state to KS_NONE and it's removed in the next cycle. //If not, this client will change to KS_CONNECTED_BUDDY when it connects. if( m_nBuddyStatus == Connected ) cur_client->SetKadState(KS_NONE); break; case KS_QUEUED_BUDDY: //We are firewalled and want to request this client to be a buddy. //But first we check to make sure we are not already trying another client. //If we are not already trying. We try to connect to this client. //If we are already connected to a buddy, we set this client to KS_NONE and it's removed next cycle. //If we are trying to connect to a buddy, we just ignore as the one we are trying may fail and we can then try this one. if( m_nBuddyStatus == Disconnected ) { buddy = Connecting; m_nBuddyStatus = Connecting; cur_client->SetKadState(KS_CONNECTING_BUDDY); cur_client->TryToConnect(true, true); theApp.emuledlg->serverwnd->UpdateMyInfo(); } else if( m_nBuddyStatus == Connected ) cur_client->SetKadState(KS_NONE); break; case KS_CONNECTING_BUDDY: //We are trying to connect to this client. //Although it should NOT happen, we make sure we are not already connected to a buddy. //If we are we set to KS_NONE and it's removed next cycle. //But if we are not already connected, make sure we set the flag to connecting so we know //things are working correctly. if( m_nBuddyStatus == Connected ) cur_client->SetKadState(KS_NONE); else { ASSERT( m_nBuddyStatus == Connecting ); buddy = Connecting; } break; case KS_CONNECTED_BUDDY: //A potential connected buddy client wanting to me in the Kad network //We set our flag to connected to make sure things are still working correctly. buddy = Connected; //If m_nBuddyStatus is not connected already, we set this client as our buddy! if( m_nBuddyStatus != Connected ) { m_pBuddy = cur_client; m_nBuddyStatus = Connected; theApp.emuledlg->serverwnd->UpdateMyInfo(); } if( m_pBuddy == cur_client && theApp.IsFirewalled() && cur_client->SendBuddyPingPong() ) { if (thePrefs.GetDebugClientTCPLevel() > 0) DebugSend("OP__BuddyPing", cur_client); Packet* buddyPing = new Packet(OP_BUDDYPING, 0, OP_EMULEPROT); theStats.AddUpDataOverheadOther(buddyPing->size); VERIFY( cur_client->SendPacket(buddyPing, true, true) ); cur_client->SetLastBuddyPingPongTime(); } break; default: RemoveFromKadList(cur_client); } } //We either never had a buddy, or lost our buddy.. if( buddy == Disconnected ) { if( m_nBuddyStatus != Disconnected || m_pBuddy ) { if( Kademlia::CKademlia::IsRunning() && theApp.IsFirewalled() && Kademlia::CUDPFirewallTester::IsFirewalledUDP(true)) { //We are a lowID client and we just lost our buddy. //Go ahead and instantly try to find a new buddy. Kademlia::CKademlia::GetPrefs()->SetFindBuddy(); } m_pBuddy = NULL; m_nBuddyStatus = Disconnected; theApp.emuledlg->serverwnd->UpdateMyInfo(); } } if ( Kademlia::CKademlia::IsConnected() ) { //we only need a buddy if direct callback is not available if( Kademlia::CKademlia::IsFirewalled() && Kademlia::CUDPFirewallTester::IsFirewalledUDP(true)) { //TODO 0.49b: Kad buddies won'T work with RequireCrypt, so it is disabled for now but should (and will) //be fixed in later version // Update: Buddy connections itself support obfuscation properly since 0.49a (this makes it work fine if our buddy uses require crypt) // ,however callback requests don't support it yet so we wouldn't be able to answer callback requests with RequireCrypt, protocolchange intended for the next version if( m_nBuddyStatus == Disconnected && Kademlia::CKademlia::GetPrefs()->GetFindBuddy() && !thePrefs.IsClientCryptLayerRequired()) { DEBUG_ONLY( DebugLog(_T("Starting Buddysearch")) ); //We are a firewalled client with no buddy. We have also waited a set time //to try to avoid a false firewalled status.. So lets look for a buddy.. if( !Kademlia::CSearchManager::PrepareLookup(Kademlia::CSearch::FINDBUDDY, true, Kademlia::CUInt128(true).Xor(Kademlia::CKademlia::GetPrefs()->GetKadID())) ) { //This search ID was already going. Most likely reason is that //we found and lost our buddy very quickly and the last search hadn't //had time to be removed yet. Go ahead and set this to happen again //next time around. Kademlia::CKademlia::GetPrefs()->SetFindBuddy(); } } } else { if( m_pBuddy ) { //Lets make sure that if we have a buddy, they are firewalled! //If they are also not firewalled, then someone must have fixed their firewall or stopped saturating their line.. //We just set the state of this buddy to KS_NONE and things will be cleared up with the next cycle. if( !m_pBuddy->HasLowID() ) m_pBuddy->SetKadState(KS_NONE); } } } else { if( m_pBuddy ) { //We are not connected anymore. Just set this buddy to KS_NONE and things will be cleared out on next cycle. m_pBuddy->SetKadState(KS_NONE); } } /////////////////////////////////////////////////////////////////////////// // Cleanup client list // CleanUpClientList(); /////////////////////////////////////////////////////////////////////////// // Process Direct Callbacks for Timeouts // ProcessConnectingClientsList(); }
void CClientList::Process() { const uint32 cur_tick = ::GetTickCount(); if (m_dwLastBannCleanUp + BAN_CLEANUP_TIME < cur_tick) { m_dwLastBannCleanUp = cur_tick; ClientMap::iterator it = m_bannedList.begin(); while ( it != m_bannedList.end() ) { if ( it->second + CLIENTBANTIME < cur_tick ) { ClientMap::iterator tmp = it++; m_bannedList.erase( tmp ); theStats::RemoveBannedClient(); } else { ++it; } } } if ( m_dwLastTrackedCleanUp + TRACKED_CLEANUP_TIME < cur_tick ) { m_dwLastTrackedCleanUp = cur_tick; std::map<uint32, CDeletedClient*>::iterator it = m_trackedClientsList.begin(); while ( it != m_trackedClientsList.end() ) { std::map<uint32, CDeletedClient*>::iterator cur_src = it++; if ( cur_src->second->m_dwInserted + KEEPTRACK_TIME < cur_tick ) { delete cur_src->second; m_trackedClientsList.erase( cur_src ); } } } //We need to try to connect to the clients in m_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. // buddy is just a flag that is used to make sure we are still connected or connecting to a buddy. buddyState buddy = Disconnected; CClientRefSet::iterator current_it = m_KadSources.begin(); while (current_it != m_KadSources.end()) { CUpDownClient* cur_client = current_it->GetClient(); ++current_it; // Won't be used anymore till while loop if( !Kademlia::CKademlia::IsRunning() ) { //Clear out this list if we stop running Kad. //Setting the Kad state to KS_NONE causes it to be removed in the switch below. cur_client->SetKadState(KS_NONE); } switch (cur_client->GetKadState()) { case KS_QUEUED_FWCHECK: case KS_QUEUED_FWCHECK_UDP: //Another client asked us to try to connect to them to check their firewalled status. cur_client->TryToConnect(true); break; case KS_CONNECTING_FWCHECK: //Ignore this state as we are just waiting for results. break; case KS_FWCHECK_UDP: case KS_CONNECTING_FWCHECK_UDP: // We want a UDP firewallcheck from this client and are just waiting to get connected to send the request break; case KS_CONNECTED_FWCHECK: //We successfully connected to the client. //We now send a ack to let them know. if (cur_client->GetKadVersion() >= 7) { // The result is now sent per TCP instead of UDP, because this will fail if our intern port is unreachable. // But we want the TCP testresult regardless if UDP is firewalled, the new UDP state and test takes care of the rest wxASSERT(cur_client->IsConnected()); AddDebugLogLineN(logLocalClient, wxT("Local Client: OP_KAD_FWTCPCHECK_ACK to ") + Uint32toStringIP(cur_client->GetIP())); CPacket *packet = new CPacket(OP_KAD_FWTCPCHECK_ACK, 0, OP_EMULEPROT); cur_client->SafeSendPacket(packet); } else { AddDebugLogLineN(logClientKadUDP, wxT("KadFirewalledAckRes to ") + Uint32_16toStringIP_Port(cur_client->GetIP(), cur_client->GetKadPort())); Kademlia::CKademlia::GetUDPListener()->SendNullPacket(KADEMLIA_FIREWALLED_ACK_RES, wxUINT32_SWAP_ALWAYS(cur_client->GetIP()), cur_client->GetKadPort(), 0, NULL); } //We are done with this client. Set Kad status to KS_NONE and it will be removed in the next cycle. cur_client->SetKadState(KS_NONE); break; case KS_INCOMING_BUDDY: //A firewalled client wants us to be his buddy. //If we already have a buddy, we set Kad state to KS_NONE and it's removed in the next cycle. //If not, this client will change to KS_CONNECTED_BUDDY when it connects. if( m_nBuddyStatus == Connected ) { cur_client->SetKadState(KS_NONE); } break; case KS_QUEUED_BUDDY: //We are firewalled and want to request this client to be a buddy. //But first we check to make sure we are not already trying another client. //If we are not already trying. We try to connect to this client. //If we are already connected to a buddy, we set this client to KS_NONE and it's removed next cycle. //If we are trying to connect to a buddy, we just ignore as the one we are trying may fail and we can then try this one. if( m_nBuddyStatus == Disconnected ) { buddy = Connecting; m_nBuddyStatus = Connecting; cur_client->SetKadState(KS_CONNECTING_BUDDY); cur_client->TryToConnect(true); Notify_ServerUpdateED2KInfo(); } else { if( m_nBuddyStatus == Connected ) { cur_client->SetKadState(KS_NONE); } } break; case KS_CONNECTING_BUDDY: //We are trying to connect to this client. //Although it should NOT happen, we make sure we are not already connected to a buddy. //If we are we set to KS_NONE and it's removed next cycle. //But if we are not already connected, make sure we set the flag to connecting so we know //things are working correctly. if( m_nBuddyStatus == Connected ) { cur_client->SetKadState(KS_NONE); } else { wxASSERT( m_nBuddyStatus == Connecting ); buddy = Connecting; } break; case KS_CONNECTED_BUDDY: //A potential connected buddy client wanting to me in the Kad network //We set our flag to connected to make sure things are still working correctly. buddy = Connected; //If m_nBuddyStatus is not connected already, we set this client as our buddy! if( m_nBuddyStatus != Connected ) { m_pBuddy.Link(cur_client CLIENT_DEBUGSTRING("CClientList::Process KS_CONNECTED_BUDDY m_pBuddy.Link")); m_nBuddyStatus = Connected; Notify_ServerUpdateED2KInfo(); } if( m_pBuddy.GetClient() == cur_client && theApp->IsFirewalled() && cur_client->SendBuddyPingPong() ) { cur_client->SendBuddyPing(); } break; default: RemoveFromKadList(cur_client); } } //We either never had a buddy, or lost our buddy.. if( buddy == Disconnected ) { if( m_nBuddyStatus != Disconnected || m_pBuddy.IsLinked() ) { if( Kademlia::CKademlia::IsRunning() && theApp->IsFirewalled() && Kademlia::CUDPFirewallTester::IsFirewalledUDP(true) ) { //We are a lowID client and we just lost our buddy. //Go ahead and instantly try to find a new buddy. Kademlia::CKademlia::GetPrefs()->SetFindBuddy(); } m_pBuddy.Unlink(); m_nBuddyStatus = Disconnected; Notify_ServerUpdateED2KInfo(); } } if ( Kademlia::CKademlia::IsConnected() ) { // we only need a buddy if direct callback is not available if(Kademlia::CKademlia::IsFirewalled() && Kademlia::CUDPFirewallTester::IsFirewalledUDP(true)) { // TODO: Kad buddies won't work with RequireCrypt, so it is disabled for now, but should (and will) // be fixed in later version // Update: buddy connections themselves support obfuscation properly since eMule 0.49a and aMule SVN 2008-05-09 // (this makes it work fine if our buddy uses require crypt), however callback requests don't support it yet so we // wouldn't be able to answer callback requests with RequireCrypt, protocolchange intended for eMule 0.49b if(m_nBuddyStatus == Disconnected && Kademlia::CKademlia::GetPrefs()->GetFindBuddy() && !thePrefs::IsClientCryptLayerRequired()) { AddDebugLogLineN(logKadMain, wxT("Starting BuddySearch")); //We are a firewalled client with no buddy. We have also waited a set time //to try to avoid a false firewalled status.. So lets look for a buddy.. if (!Kademlia::CSearchManager::PrepareLookup(Kademlia::CSearch::FINDBUDDY, true, Kademlia::CUInt128(true) ^ (Kademlia::CKademlia::GetPrefs()->GetKadID()))) { //This search ID was already going. Most likely reason is that //we found and lost our buddy very quickly and the last search hadn't //had time to be removed yet. Go ahead and set this to happen again //next time around. Kademlia::CKademlia::GetPrefs()->SetFindBuddy(); } } } else { if (m_pBuddy.IsLinked()) { //Lets make sure that if we have a buddy, they are firewalled! //If they are also not firewalled, then someone must have fixed their firewall or stopped saturating their line.. //We just set the state of this buddy to KS_NONE and things will be cleared up with the next cycle. if( !m_pBuddy.HasLowID() ) { m_pBuddy.GetClient()->SetKadState(KS_NONE); } } } } else { if (m_pBuddy.IsLinked()) { //We are not connected anymore. Just set this buddy to KS_NONE and things will be cleared out on next cycle. m_pBuddy.GetClient()->SetKadState(KS_NONE); } } CleanUpClientList(); ProcessDirectCallbackList(); }