//This is used when we find a leaf and want to know what this sample looks like. //We fall back two levels and take a sample to try to minimize any areas of the //tree that will give very bad results. uint32 CRoutingZone::EstimateCount() { if( !IsLeaf() ) return 0; if( m_uLevel < KBASE ) return (UINT)(pow(2.0F, (int)m_uLevel)*K); CRoutingZone* pCurZone = m_pSuperZone->m_pSuperZone->m_pSuperZone; // Find out how full this part of the tree is. float fModify = ((float)pCurZone->GetNumContacts())/(float)(K*2); // First calculate users assuming the tree is full. // Modify count by bin size. // Modify count by how full the tree is. // Modify count by assuming 20% of the users are firewalled and can't be a contact. return (UINT)((pow(2.0F, (int)m_uLevel-2))*(float)K*fModify*(1.20F)); }
//This is used when we find a leaf and want to know what this sample looks like. //We fall back two levels and take a sample to try to minimize any areas of the //tree that will give very bad results. uint32_t CRoutingZone::EstimateCount() const { if (!IsLeaf()) { return 0; } if (m_level < KBASE) { return (uint32_t)(pow(2.0, (int)m_level) * K); } CRoutingZone* curZone = m_superZone->m_superZone->m_superZone; // Find out how full this part of the tree is. float modify = ((float)curZone->GetNumContacts()) / (float)(K * 2); // First calculate users assuming the tree is full. // Modify count by bin size. // Modify count by how full the tree is. // LowIDModififier // Modify count by assuming 20% of the users are firewalled and can't be a contact for < 0.49b nodes // Modify count by actual statistics of Firewalled ratio for >= 0.49b if we are not firewalled ourself // Modify count by 40% for >= 0.49b if we are firewalled ourself (the actual Firewalled count at this date on kad is 35-55%) const float firewalledModifyOld = 1.20f; float firewalledModifyNew = 0; if (CUDPFirewallTester::IsFirewalledUDP(true)) { firewalledModifyNew = 1.40f; // we are firewalled and can't get the real statistics, assume 40% firewalled >=0.49b nodes } else if (CKademlia::GetPrefs()->StatsGetFirewalledRatio(true) > 0) { firewalledModifyNew = 1.0 + (CKademlia::GetPrefs()->StatsGetFirewalledRatio(true)); // apply the firewalled ratio to the modify ASSERT(firewalledModifyNew > 1.0 && firewalledModifyNew < 1.90); } float newRatio = CKademlia::GetPrefs()->StatsGetKadV8Ratio(); float firewalledModifyTotal = 0; if (newRatio > 0 && firewalledModifyNew > 0) { // weight the old and the new modifier based on how many new contacts we have firewalledModifyTotal = (newRatio * firewalledModifyNew) + ((1 - newRatio) * firewalledModifyOld); } else { firewalledModifyTotal = firewalledModifyOld; } ASSERT(firewalledModifyTotal > 1.0 && firewalledModifyTotal < 1.90); return (uint32_t)(pow(2.0, (int)m_level - 2) * (float)K * modify * firewalledModifyTotal); }
//This is used when we find a leaf and want to know what this sample looks like. //We fall back two levels and take a sample to try to minimize any areas of the //tree that will give very bad results. uint32_t CRoutingZone::EstimateCount() { if( !IsLeaf() ) return 0; if( m_uLevel < KBASE ) return (UINT)(pow(2.0F, (int)m_uLevel)*K); CRoutingZone* pCurZone = m_pSuperZone->m_pSuperZone->m_pSuperZone; // Find out how full this part of the tree is. float fModify = ((float)pCurZone->GetNumContacts())/(float)(K*2); // First calculate users assuming the tree is full. // Modify count by bin size. // Modify count by how full the tree is. // LowIDModififier // Modify count by assuming 20% of the users are firewalled and can't be a contact for < 0.49b nodes // Modify count by actual statistics of Firewalled ratio for >= 0.49b if we are not firewalled ourself // Modify count by 40% for >= 0.49b if we are firewalled outself (the actual Firewalled count at this date on kad is 35-55%) const float fFirewalledModifyOld = 1.20F; float fFirewalledModifyNew = 0; if (CUDPFirewallTester::IsFirewalledUDP(true)) fFirewalledModifyNew = 1.40F; // we are firewalled and get get the real statistic, assume 40% firewalled >=0.49b nodes else if (CKademlia::GetPrefs()->StatsGetFirewalledRatio(true) > 0) { fFirewalledModifyNew = 1.0F + (CKademlia::GetPrefs()->StatsGetFirewalledRatio(true)); // apply the firewalled ratio to the modify ASSERT( fFirewalledModifyNew > 1.0F && fFirewalledModifyNew < 1.90F ); } float fNewRatio = CKademlia::GetPrefs()->StatsGetKadV8Ratio(); float fFirewalledModifyTotal = 0; if (fNewRatio > 0 && fFirewalledModifyNew > 0) // weigth the old and the new modifier based on how many new contacts we have fFirewalledModifyTotal = (fNewRatio * fFirewalledModifyNew) + ((1 - fNewRatio) * fFirewalledModifyOld); else fFirewalledModifyTotal = fFirewalledModifyOld; ASSERT( fFirewalledModifyTotal > 1.0F && fFirewalledModifyTotal < 1.90F ); return (UINT)((pow(2.0F, (int)m_uLevel-2))*(float)K*fModify*fFirewalledModifyTotal); }
void CKademlia::process() { if( instance == NULL || !m_running) return; ASSERT(instance != NULL); time_t now; CRoutingZone *zone; EventMap::const_iterator it; uint32 maxUsers = 0; uint32 tempUsers = 0; uint32 lastContact = 0; bool updateUserFile = false; try { now = time(NULL); ASSERT(instance->m_prefs != NULL); lastContact = instance->m_prefs->getLastContact(); CSearchManager::updateStats(); if( m_statusUpdate <= now ) { updateUserFile = true; m_statusUpdate = MIN2S(1) + now; } if( m_nextFirewallCheck <= now) { RecheckFirewalled(); } if (m_nextSelfLookup <= now) { CUInt128 me; instance->m_prefs->getKadID(&me); CSearchManager::findNodeComplete(me); m_nextSelfLookup = HR2S(4) + now; } if (m_nextFindBuddy <= now) { instance->m_prefs->setFindBuddy(); m_nextFindBuddy = MIN2S(5) + m_nextFirewallCheck; } for (it = m_events.begin(); it != m_events.end(); it++) { zone = it->first; if( updateUserFile ) { tempUsers = zone->estimateCount(); if( maxUsers < tempUsers ) maxUsers = tempUsers; } if (m_bigTimer <= now) { try { if( zone->m_nextBigTimer <= now ) { if(zone->onBigTimer()) { zone->m_nextBigTimer = HR2S(1) + now; m_bigTimer = SEC(10) + now; } } else { if( lastContact && ( (now - lastContact) > (KADEMLIADISCONNECTDELAY-MIN2S(5)))) { if(zone->onBigTimer()) { zone->m_nextBigTimer = HR2S(1) + now; m_bigTimer = SEC(10) + now; } } } } catch (...) { AddDebugLogLine(false, _T("Exception in Kademlia::Process(1)")); } } if (zone->m_nextSmallTimer <= now) { try { zone->onSmallTimer(); } catch (...) { AddDebugLogLine(false, _T("Exception in Kademlia::Process(2)")); } zone->m_nextSmallTimer = MIN2S(1) + now; } // This is a convenient place to add this, although not related to routing if (m_nextSearchJumpStart <= now) { try { CSearchManager::jumpStart(); } catch (...) { AddDebugLogLine(false, _T("Exception in Kademlia::Process(3)")); } m_nextSearchJumpStart += SEARCH_JUMPSTART; } } //Update user count only if changed. if( updateUserFile ) { if( maxUsers != instance->m_prefs->getKademliaUsers()) { instance->m_prefs->setKademliaUsers(maxUsers); instance->m_prefs->setKademliaFiles(); theApp.emuledlg->ShowUserCount(); } } } catch (...) { AddDebugLogLine(false, _T("Exception in Kademlia::Process(4)")); } }
void CKademlia::Process() { if (instance == NULL || !m_running) { return; } time_t now = time(NULL); uint32_t maxUsers = 0; uint32_t tempUsers = 0; uint32_t lastContact = 0; bool updateUserFile = false; wxASSERT(instance->m_prefs != NULL); lastContact = instance->m_prefs->GetLastContact(); CSearchManager::UpdateStats(); if (m_statusUpdate <= now) { updateUserFile = true; m_statusUpdate = MIN2S(1) + now; } if (m_nextFirewallCheck <= now) { RecheckFirewalled(); } if (m_nextSelfLookup <= now) { CSearchManager::FindNode(instance->m_prefs->GetKadID(), true); m_nextSelfLookup = HR2S(4) + now; } if (m_nextFindBuddy <= now) { instance->m_prefs->SetFindBuddy(); m_nextFindBuddy = MIN2S(20) + now; } if (m_externPortLookup <= now && CUDPFirewallTester::IsFWCheckUDPRunning() && GetPrefs()->FindExternKadPort(false)) { // If our UDP firewallcheck is running and we don't know our external port, we send a request every 15 seconds CContact *contact = GetRoutingZone()->GetRandomContact(3, 6); if (contact != NULL) { AddDebugLogLineN(logKadPrefs, wxT("Requesting our external port from ") + KadIPToString(contact->GetIPAddress())); DebugSend(Kad2Ping, contact->GetIPAddress(), contact->GetUDPPort()); GetUDPListener()->SendNullPacket(KADEMLIA2_PING, contact->GetIPAddress(), contact->GetUDPPort(), contact->GetUDPKey(), &contact->GetClientID()); } else { AddDebugLogLineN(logKadPrefs, wxT("No valid client for requesting external port available")); } m_externPortLookup = 15 + now; } for (EventMap::const_iterator it = m_events.begin(); it != m_events.end(); ++it) { CRoutingZone *zone = it->first; if (updateUserFile) { // The EstimateCount function is not made for really small networks, if we are in LAN mode, it is actually // better to assume that all users of the network are in our routing table and use the real count function if (IsRunningInLANMode()) { tempUsers = zone->GetNumContacts(); } else { tempUsers = zone->EstimateCount(); } if (maxUsers < tempUsers) { maxUsers = tempUsers; } } if (m_bigTimer <= now) { if (zone->m_nextBigTimer <= now) { if(zone->OnBigTimer()) { zone->m_nextBigTimer = HR2S(1) + now; m_bigTimer = SEC(10) + now; } } else { if (lastContact && (now - lastContact > KADEMLIADISCONNECTDELAY - MIN2S(5))) { if(zone->OnBigTimer()) { zone->m_nextBigTimer = HR2S(1) + now; m_bigTimer = SEC(10) + now; } } } } if (zone->m_nextSmallTimer <= now) { zone->OnSmallTimer(); zone->m_nextSmallTimer = MIN2S(1) + now; } } // This is a convenient place to add this, although not related to routing if (m_nextSearchJumpStart <= now) { CSearchManager::JumpStart(); m_nextSearchJumpStart = SEARCH_JUMPSTART + now; } // Try to consolidate any zones that are close to empty. if (m_consolidate <= now) { uint32_t mergedCount = instance->m_routingZone->Consolidate(); if (mergedCount) { AddDebugLogLineN(logKadRouting, CFormat(wxT("Kad merged %u zones")) % mergedCount); } m_consolidate = MIN2S(45) + now; } // Update user count only if changed. if (updateUserFile) { if (maxUsers != instance->m_prefs->GetKademliaUsers()) { instance->m_prefs->SetKademliaUsers(maxUsers); instance->m_prefs->SetKademliaFiles(); theApp->ShowUserCount(); } } if (!IsConnected() && !s_bootstrapList.empty() && (now - m_bootstrap > 15 || (GetRoutingZone()->GetNumContacts() == 0 && now - m_bootstrap >= 2))) { CContact *contact = s_bootstrapList.front(); s_bootstrapList.pop_front(); m_bootstrap = now; AddDebugLogLineN(logKadMain, CFormat(wxT("Trying to bootstrap Kad from %s, Distance: %s Version: %u, %u contacts left")) % KadIPToString(contact->GetIPAddress()) % contact->GetDistance().ToHexString() % contact->GetVersion() % s_bootstrapList.size()); instance->m_udpListener->Bootstrap(contact->GetIPAddress(), contact->GetUDPPort(), contact->GetVersion(), &contact->GetClientID()); delete contact; } if (GetUDPListener() != NULL) { GetUDPListener()->ExpireClientSearch(); // function does only one compare in most cases, so no real need for a timer } }
void CKademlia::Process() { if( m_pInstance == NULL || !m_bRunning) return; bool bUpdateUserFile = false; uint32_t uMaxUsers = 0; uint32_t uTempUsers = 0; time_t uLastContact = 0; time_t tNow = time(NULL); ASSERT(m_pInstance->m_pPrefs != NULL); uLastContact = m_pInstance->m_pPrefs->GetLastContact(); CSearchManager::UpdateStats(); if( m_tStatusUpdate <= tNow ) { bUpdateUserFile = true; m_tStatusUpdate = MIN2S(1) + tNow; } if( m_tNextFirewallCheck <= tNow) RecheckFirewalled(); if (m_tNextUPnPCheck != 0 && m_tNextUPnPCheck <= tNow) { theApp.emuledlg->RefreshUPnP(); m_tNextUPnPCheck = 0; // will be reset on firewallcheck } if (m_tNextSelfLookup <= tNow) { CSearchManager::FindNode(m_pInstance->m_pPrefs->GetKadID(), true); m_tNextSelfLookup = HR2S(4) + tNow; } if (m_tNextFindBuddy <= tNow) { m_pInstance->m_pPrefs->SetFindBuddy(); m_tNextFindBuddy = MIN2S(20) + tNow; } if (m_tExternPortLookup <= tNow && CUDPFirewallTester::IsFWCheckUDPRunning() && GetPrefs()->FindExternKadPort(false)){ // if our UDP firewallcheck is running and we don't know our external port, we send a request every 15 seconds CContact* pContact = GetRoutingZone()->GetRandomContact(3, KADEMLIA_VERSION6_49aBETA); if (pContact != NULL){ DEBUG_ONLY( DebugLog(_T("Requesting our external port from %s"), ipstr(ntohl(pContact->GetIPAddress()))) ); GetUDPListener()->SendNullPacket(KADEMLIA2_PING, pContact->GetIPAddress(), pContact->GetUDPPort(), pContact->GetUDPKey(), &pContact->GetClientID()); } else DEBUG_ONLY( DebugLogWarning(_T("No valid client for requesting external port available")) ); m_tExternPortLookup = 15 + tNow; } for (EventMap::const_iterator itEventMap = m_mapEvents.begin(); itEventMap != m_mapEvents.end(); ++itEventMap) { CRoutingZone* pZone = itEventMap->first; if( bUpdateUserFile ) { uTempUsers = pZone->EstimateCount(); if( uMaxUsers < uTempUsers ) uMaxUsers = uTempUsers; } if (m_tBigTimer <= tNow) { if( pZone->m_tNextBigTimer <= tNow ) { if(pZone->OnBigTimer()) { pZone->m_tNextBigTimer = HR2S(1) + tNow; m_tBigTimer = SEC(10) + tNow; } } else { if( uLastContact && ( (tNow - uLastContact) > (KADEMLIADISCONNECTDELAY-MIN2S(5)))) { if(pZone->OnBigTimer()) { pZone->m_tNextBigTimer = HR2S(1) + tNow; m_tBigTimer = SEC(10) + tNow; } } } } if (pZone->m_tNextSmallTimer <= tNow) { pZone->OnSmallTimer(); pZone->m_tNextSmallTimer = MIN2S(1) + tNow; } } // This is a convenient place to add this, although not related to routing if (m_tNextSearchJumpStart <= tNow) { CSearchManager::JumpStart(); m_tNextSearchJumpStart = SEARCH_JUMPSTART + tNow; } // Try to consolidate any zones that are close to empty. if (m_tConsolidate <= tNow) { uint32_t uMergedCount = m_pInstance->m_pRoutingZone->Consolidate(); if(uMergedCount) AddDebugLogLine(false, _T("Kad merged %u Zones"), uMergedCount); m_tConsolidate = MIN2S(45) + tNow; } //Update user count only if changed. if( bUpdateUserFile ) { if( uMaxUsers != m_pInstance->m_pPrefs->GetKademliaUsers()) { m_pInstance->m_pPrefs->SetKademliaUsers(uMaxUsers); m_pInstance->m_pPrefs->SetKademliaFiles(); theApp.emuledlg->ShowUserCount(); } } if(!IsConnected() && !s_liBootstapList.IsEmpty() && (tNow - m_tBootstrap > 15 || (GetRoutingZone()->GetNumContacts() == 0 && tNow - m_tBootstrap >= 2))) { CContact* pContact = s_liBootstapList.RemoveHead(); m_tBootstrap = tNow; DebugLog(_T("Trying to Bootstrap Kad from %s, Distance: %s, Version: %u, %u Contacts left"), ipstr(ntohl(pContact->GetIPAddress())), pContact->GetDistance().ToHexString(), pContact->GetVersion(), s_liBootstapList.GetCount()); m_pInstance->m_pUDPListener->Bootstrap(pContact->GetIPAddress(), pContact->GetUDPPort(), pContact->GetVersion() > 1, pContact->GetVersion(), &pContact->GetClientID()); delete pContact; } if (GetUDPListener() != NULL) GetUDPListener()->ExpireClientSearch(); // function does only one compare in most cases, so no real need for a timer }
void CKademlia::Process() { if( m_pInstance == NULL || !m_bRunning) return; bool bUpdateUserFile = false; uint32 uMaxUsers = 0; uint32 uTempUsers = 0; uint32 uLastContact = 0; time_t tNow = time(NULL); ASSERT(m_pInstance->m_pPrefs != NULL); uLastContact = m_pInstance->m_pPrefs->GetLastContact(); CSearchManager::UpdateStats(); if( m_tStatusUpdate <= tNow ) { bUpdateUserFile = true; m_tStatusUpdate = MIN2S(1) + tNow; #ifdef _BOOTSTRAPNODESDAT // do some random lookup to fill out contact list with fresh (but for routing useless) nodes which we can // use for our bootstrap nodes.dat if (GetRoutingZone()->GetNumContacts() < 1500) { CUInt128 uRandom; uRandom.SetValueRandom(); CSearchManager::FindNode(uRandom, false); } #endif } if( m_tNextFirewallCheck <= tNow) RecheckFirewalled(); if (m_tNextUPnPCheck != 0 && m_tNextUPnPCheck <= tNow) { theApp.emuledlg->RefreshUPnP(); m_tNextUPnPCheck = 0; // will be reset on firewallcheck } if (m_tNextSelfLookup <= tNow) { CSearchManager::FindNode(m_pInstance->m_pPrefs->GetKadID(), true); m_tNextSelfLookup = HR2S(4) + tNow; } if (m_tNextFindBuddy <= tNow) { m_pInstance->m_pPrefs->SetFindBuddy(); m_tNextFindBuddy = MIN2S(20) + tNow; } if (m_tExternPortLookup <= tNow && CUDPFirewallTester::IsFWCheckUDPRunning() && GetPrefs()->FindExternKadPort(false)){ // if our UDP firewallcheck is running and we don't know our external port, we send a request every 15 seconds CContact* pContact = GetRoutingZone()->GetRandomContact(3, KADEMLIA_VERSION6_49aBETA); if (pContact != NULL){ DEBUG_ONLY( DebugLog(_T("Requesting our external port from %s"), ipstr(ntohl(pContact->GetIPAddress()))) ); GetUDPListener()->SendNullPacket(KADEMLIA2_PING, pContact->GetIPAddress(), pContact->GetUDPPort(), pContact->GetUDPKey(), &pContact->GetClientID()); } else DEBUG_ONLY( DebugLogWarning(_T("No valid client for requesting external port available")) ); m_tExternPortLookup = 15 + tNow; } for (EventMap::const_iterator itEventMap = m_mapEvents.begin(); itEventMap != m_mapEvents.end(); ++itEventMap) { CRoutingZone* pZone = itEventMap->first; if( bUpdateUserFile ) { // The EstimateCount function is not made for really small networks, if we are in LAN mode, it is actually // better to assume that all users of the network are in our routingtable and use the real count function if (IsRunningInLANMode()) uTempUsers = pZone->GetNumContacts(); else uTempUsers = pZone->EstimateCount(); if( uMaxUsers < uTempUsers ) uMaxUsers = uTempUsers; } if (m_tBigTimer <= tNow) { if( pZone->m_tNextBigTimer <= tNow ) { if(pZone->OnBigTimer()) { pZone->m_tNextBigTimer = HR2S(1) + tNow; m_tBigTimer = SEC(10) + tNow; } } else { if( uLastContact && ( (tNow - uLastContact) > (KADEMLIADISCONNECTDELAY-MIN2S(5)))) { if(pZone->OnBigTimer()) { pZone->m_tNextBigTimer = HR2S(1) + tNow; m_tBigTimer = SEC(10) + tNow; } } } } if (pZone->m_tNextSmallTimer <= tNow) { pZone->OnSmallTimer(); pZone->m_tNextSmallTimer = MIN2S(1) + tNow; } } // This is a convenient place to add this, although not related to routing if (m_tNextSearchJumpStart <= tNow) { CSearchManager::JumpStart(); m_tNextSearchJumpStart = SEARCH_JUMPSTART + tNow; } // Try to consolidate any zones that are close to empty. if (m_tConsolidate <= tNow) { uint32 uMergedCount = m_pInstance->m_pRoutingZone->Consolidate(); if(uMergedCount) AddDebugLogLine(false, _T("Kad merged %u Zones"), uMergedCount); m_tConsolidate = MIN2S(45) + tNow; } //Update user count only if changed. if( bUpdateUserFile ) { if( uMaxUsers != m_pInstance->m_pPrefs->GetKademliaUsers()) { m_pInstance->m_pPrefs->SetKademliaUsers(uMaxUsers); m_pInstance->m_pPrefs->SetKademliaFiles(); theApp.emuledlg->ShowUserCount(); } } if(!IsConnected() && !s_liBootstapList.IsEmpty() && (tNow - m_tBootstrap > 15 || (GetRoutingZone()->GetNumContacts() == 0 && tNow - m_tBootstrap >= 2))) { if (!s_liTriedBootstapList.IsEmpty()) { CContact* pLastTriedContact = s_liTriedBootstapList.GetHead(); pLastTriedContact->SetBootstrapFailed(); theApp.emuledlg->kademliawnd->ContactRef(pLastTriedContact); } CContact* pContact = s_liBootstapList.RemoveHead(); m_tBootstrap = tNow; DebugLog(_T("Trying to Bootstrap Kad from %s, Distance: %s, Version: %u, %u Contacts left"), ipstr(ntohl(pContact->GetIPAddress())), pContact->GetDistance().ToHexString(), pContact->GetVersion(), s_liBootstapList.GetCount()); m_pInstance->m_pUDPListener->Bootstrap(pContact->GetIPAddress(), pContact->GetUDPPort(), pContact->GetVersion(), &pContact->GetClientID()); s_liTriedBootstapList.AddHead(pContact); } else if (!IsConnected() && s_liBootstapList.IsEmpty() && !s_liTriedBootstapList.IsEmpty() && (tNow - m_tBootstrap > 15 || (GetRoutingZone()->GetNumContacts() == 0 && tNow - m_tBootstrap >= 2))) { // failed to bootstrap AddLogLine(true, GetResString(IDS_BOOTSTRAPFAILED)); theApp.emuledlg->kademliawnd->StopUpdateContacts(); while (!s_liTriedBootstapList.IsEmpty()) delete s_liTriedBootstapList.RemoveHead(); theApp.emuledlg->kademliawnd->StartUpdateContacts(); } if (GetUDPListener() != NULL) GetUDPListener()->ExpireClientSearch(); // function does only one compare in most cases, so no real need for a timer }