diff --git a/NetDb.cpp b/NetDb.cpp index 2f30890b..c8237865 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -108,6 +108,9 @@ namespace data void NetDb::Stop () { + for (auto it: m_RouterInfos) + it.second->SaveProfile (); + m_RouterInfos.clear (); if (m_Thread) { m_IsRunning = false; @@ -173,8 +176,7 @@ namespace data } lastSave = ts; } - if (i2p::context.GetLastUpdateTime () > lastPublish || // our router has been updated - ts - lastPublish >= 2400) // or publish every 40 minutes + if (ts - lastPublish >= 2400) // publish every 40 minutes { Publish (); lastPublish = ts; @@ -461,7 +463,10 @@ namespace data for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { if (it->second->IsUnreachable ()) + { + it->second->SaveProfile (); it = m_RouterInfos.erase (it); + } else it++; } @@ -861,7 +866,6 @@ namespace data void NetDb::Publish () { - i2p::context.UpdateStats (); std::set excluded; // TODO: fill up later for (int i = 0; i < 2; i++) { @@ -919,7 +923,7 @@ namespace data [compatibleWith](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith) && router->IsHighBandwidth (); + router->IsCompatible (*compatibleWith) && (router->GetCaps () & RouterInfo::eHighBandwidth); }); } diff --git a/Profiling.cpp b/Profiling.cpp index 269ad773..b5558972 100644 --- a/Profiling.cpp +++ b/Profiling.cpp @@ -1,5 +1,8 @@ +#include #include #include +#include "base64.h" +#include "util.h" #include "Profiling.h" namespace i2p @@ -10,8 +13,60 @@ namespace data m_IdentHash (identHash), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0) { } - - std::shared_ptr GetProfile (const IdentHash& identHash) + + void RouterProfile::Save () + { + // fill sections + boost::property_tree::ptree participation; + participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); + participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); + // fill property tree + boost::property_tree::ptree pt; + pt.put_child (PEER_PROFILE_SECTION_PARTICIPATION, participation); + + // save to file + auto path = i2p::util::filesystem::GetDefaultDataDir() / PEER_PROFILES_DIRECTORY; + if (!boost::filesystem::exists (path)) + { + // Create directory is necessary + if (!boost::filesystem::create_directory (path)) + { + LogPrint (eLogError, "Failed to create directory ", path); + return; + } + const char * chars = GetBase64SubstitutionTable (); // 64 bytes + for (int i = 0; i < 64; i++) + { + auto path1 = path / (std::string ("p") + chars[i]); + if (!boost::filesystem::create_directory (path1)) + { + LogPrint (eLogError, "Failed to create directory ", path1); + return; + } + } + } + std::string base64 = m_IdentHash.ToBase64 (); + path = path / (std::string ("p") + base64[0]); + auto filename = path / (std::string (PEER_PROFILE_PREFIX) + base64 + ".txt"); + try + { + boost::property_tree::write_ini (filename.string (), pt); + } + catch (std::exception& ex) + { + LogPrint (eLogError, "Can't write ", filename, ": ", ex.what ()); + } + } + + void RouterProfile::TunnelBuildResponse (uint8_t ret) + { + if (ret > 0) + m_NumTunnelsDeclined++; + else + m_NumTunnelsAgreed++; + } + + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { return std::make_shared (identHash); } diff --git a/Profiling.h b/Profiling.h index c20934a7..4e048ef0 100644 --- a/Profiling.h +++ b/Profiling.h @@ -7,12 +7,23 @@ namespace i2p { namespace data -{ +{ + const char PEER_PROFILES_DIRECTORY[] = "peerProfiles"; + const char PEER_PROFILE_PREFIX[] = "profile-"; + // sections + const char PEER_PROFILE_SECTION_PARTICIPATION[] = "participation"; + // params + const char PEER_PROFILE_PARTICIPATION_AGREED[] = "agreed"; + const char PEER_PROFILE_PARTICIPATION_DECLINED[] = "declined"; + class RouterProfile { public: RouterProfile (const IdentHash& identHash); + void Save (); + + void TunnelBuildResponse (uint8_t ret); private: @@ -22,7 +33,7 @@ namespace data uint32_t m_NumTunnelsDeclined; }; - std::shared_ptr GetProfile (const IdentHash& identHash); + std::shared_ptr GetRouterProfile (const IdentHash& identHash); } } diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 66eca3b4..a1c3533f 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -652,5 +652,12 @@ namespace data } return nullptr; } + + std::shared_ptr RouterInfo::GetProfile () const + { + if (!m_Profile) + m_Profile = GetRouterProfile (GetIdentHash ()); + return m_Profile; + } } } diff --git a/RouterInfo.h b/RouterInfo.h index 53ddb5ab..4934da32 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -138,6 +138,9 @@ namespace data void SetUpdated (bool updated) { m_IsUpdated = updated; }; void SaveToFile (const std::string& fullPath); + std::shared_ptr GetProfile () const; + void SaveProfile () { if (m_Profile) m_Profile->Save (); }; + void Update (const uint8_t * buf, int len); void DeleteBuffer () { delete m_Buffer; m_Buffer = nullptr; }; @@ -171,7 +174,7 @@ namespace data std::map m_Properties; bool m_IsUpdated, m_IsUnreachable; uint8_t m_SupportedTransports, m_Caps; - std::shared_ptr m_Profile; + mutable std::shared_ptr m_Profile; }; } } diff --git a/Tunnel.cpp b/Tunnel.cpp index f04c7f05..4852c7bd 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -121,6 +121,7 @@ namespace tunnel const uint8_t * record = msg + 1 + hop->recordIndex*TUNNEL_BUILD_RECORD_SIZE; uint8_t ret = record[BUILD_RESPONSE_RECORD_RET_OFFSET]; LogPrint ("Ret code=", (int)ret); + hop->router->GetProfile ()->TunnelBuildResponse (ret); if (ret) // if any of participants declined the tunnel is not established established = false;