2019-01-11 02:19:36 +01:00
|
|
|
#include <path/pathset.hpp>
|
|
|
|
|
2018-12-12 01:48:54 +01:00
|
|
|
#include <dht/messages/pubintro.hpp>
|
2019-01-11 02:19:36 +01:00
|
|
|
#include <path/path.hpp>
|
2019-06-15 16:55:13 +02:00
|
|
|
#include <routing/dht_message.hpp>
|
2018-06-25 17:12:08 +02:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace path
|
|
|
|
{
|
|
|
|
PathSet::PathSet(size_t num) : m_NumPaths(num)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-10-29 17:48:36 +01:00
|
|
|
PathSet::ShouldBuildMore(llarp_time_t now) const
|
2018-06-25 17:12:08 +02:00
|
|
|
{
|
2019-04-23 18:13:22 +02:00
|
|
|
(void)now;
|
2019-04-22 21:15:07 +02:00
|
|
|
const auto building = NumInStatus(ePathBuilding);
|
|
|
|
if(building > m_NumPaths)
|
|
|
|
return false;
|
|
|
|
const auto established = NumInStatus(ePathEstablished);
|
|
|
|
return established <= m_NumPaths;
|
2018-06-25 17:12:08 +02:00
|
|
|
}
|
|
|
|
|
2018-11-14 19:02:27 +01:00
|
|
|
bool
|
|
|
|
PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const
|
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-11-14 19:02:27 +01:00
|
|
|
const size_t required = MinRequiredForRoles(roles);
|
|
|
|
size_t has = 0;
|
|
|
|
for(const auto& item : m_Paths)
|
|
|
|
{
|
2018-11-21 13:31:36 +01:00
|
|
|
if(item.second->SupportsAnyRoles(roles))
|
2018-11-14 19:02:27 +01:00
|
|
|
{
|
|
|
|
if(!item.second->ExpiresSoon(now))
|
|
|
|
++has;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return has < required;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
PathSet::MinRequiredForRoles(PathRole roles) const
|
|
|
|
{
|
2018-11-19 17:48:35 +01:00
|
|
|
(void)roles;
|
|
|
|
return 0;
|
2018-11-14 19:02:27 +01:00
|
|
|
}
|
|
|
|
|
2018-11-26 14:30:03 +01:00
|
|
|
size_t
|
|
|
|
PathSet::NumPathsExistingAt(llarp_time_t futureTime) const
|
2018-11-25 17:58:27 +01:00
|
|
|
{
|
|
|
|
size_t num = 0;
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-11-26 14:30:03 +01:00
|
|
|
for(const auto& item : m_Paths)
|
2018-11-25 17:58:27 +01:00
|
|
|
{
|
2019-05-25 18:27:54 +02:00
|
|
|
if(item.second->IsReady() && !item.second->Expired(futureTime))
|
2018-11-25 17:58:27 +01:00
|
|
|
++num;
|
|
|
|
}
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
2018-06-29 18:02:39 +02:00
|
|
|
void
|
2019-04-23 18:13:22 +02:00
|
|
|
PathSet::TickPaths(llarp_time_t now, AbstractRouter* r)
|
2018-06-29 18:02:39 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-06-29 18:02:39 +02:00
|
|
|
for(auto& item : m_Paths)
|
|
|
|
{
|
2018-09-13 18:41:53 +02:00
|
|
|
item.second->Tick(now, r);
|
2018-06-29 18:02:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 17:12:08 +02:00
|
|
|
void
|
|
|
|
PathSet::ExpirePaths(llarp_time_t now)
|
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-08-17 21:49:58 +02:00
|
|
|
if(m_Paths.size() == 0)
|
|
|
|
return;
|
2018-06-26 16:52:19 +02:00
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
2018-06-25 17:12:08 +02:00
|
|
|
{
|
2018-06-26 16:52:19 +02:00
|
|
|
if(itr->second->Expired(now))
|
|
|
|
itr = m_Paths.erase(itr);
|
|
|
|
else
|
|
|
|
++itr;
|
2018-06-25 17:12:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2018-12-18 19:36:19 +01:00
|
|
|
PathSet::GetEstablishedPathClosestTo(RouterID id, PathRole roles) const
|
2018-08-02 00:10:38 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr path = nullptr;
|
2018-08-02 02:48:43 +02:00
|
|
|
AlignedBuffer< 32 > dist;
|
2019-01-02 02:03:53 +01:00
|
|
|
AlignedBuffer< 32 > to = id;
|
2018-08-02 00:10:38 +02:00
|
|
|
dist.Fill(0xff);
|
|
|
|
for(const auto& item : m_Paths)
|
|
|
|
{
|
2018-08-02 02:48:43 +02:00
|
|
|
if(!item.second->IsReady())
|
|
|
|
continue;
|
2018-11-21 13:31:36 +01:00
|
|
|
if(!item.second->SupportsAnyRoles(roles))
|
2018-11-14 19:02:27 +01:00
|
|
|
continue;
|
2018-12-10 18:22:59 +01:00
|
|
|
AlignedBuffer< 32 > localDist = item.second->Endpoint() ^ to;
|
2018-08-02 00:10:38 +02:00
|
|
|
if(localDist < dist)
|
|
|
|
{
|
|
|
|
dist = localDist;
|
|
|
|
path = item.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2018-12-18 19:36:19 +01:00
|
|
|
PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const
|
2018-09-19 01:56:26 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr chosen = nullptr;
|
2019-04-23 18:13:22 +02:00
|
|
|
auto itr = m_Paths.begin();
|
2018-09-19 01:56:26 +02:00
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
2018-11-21 13:31:36 +01:00
|
|
|
if(itr->second->IsReady() && itr->second->SupportsAnyRoles(roles))
|
2018-09-19 01:56:26 +02:00
|
|
|
{
|
|
|
|
if(itr->second->Endpoint() == id)
|
|
|
|
{
|
|
|
|
if(chosen == nullptr)
|
|
|
|
chosen = itr->second;
|
|
|
|
else if(chosen->intro.expiresAt < itr->second->intro.expiresAt)
|
|
|
|
chosen = itr->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return chosen;
|
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2018-12-18 19:36:19 +01:00
|
|
|
PathSet::GetPathByRouter(RouterID id, PathRole roles) const
|
2018-07-23 01:14:29 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr chosen = nullptr;
|
2019-04-23 18:13:22 +02:00
|
|
|
auto itr = m_Paths.begin();
|
2018-07-23 01:14:29 +02:00
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
2018-11-21 13:31:36 +01:00
|
|
|
if(itr->second->IsReady() && itr->second->SupportsAnyRoles(roles))
|
2018-07-23 09:38:29 +02:00
|
|
|
{
|
|
|
|
if(itr->second->Endpoint() == id)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
|
|
|
if(chosen == nullptr)
|
|
|
|
chosen = itr->second;
|
|
|
|
else if(chosen->intro.latency > itr->second->intro.latency)
|
|
|
|
chosen = itr->second;
|
|
|
|
}
|
2018-07-23 09:38:29 +02:00
|
|
|
}
|
2018-07-23 01:14:29 +02:00
|
|
|
++itr;
|
|
|
|
}
|
2018-09-13 18:41:53 +02:00
|
|
|
return chosen;
|
2018-07-23 01:14:29 +02:00
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2019-03-08 18:26:29 +01:00
|
|
|
PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const
|
|
|
|
{
|
|
|
|
Lock_t l(&m_PathsMutex);
|
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->IsEndpoint(ep, id))
|
|
|
|
{
|
|
|
|
return itr->second;
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2018-12-18 19:36:19 +01:00
|
|
|
PathSet::GetPathByID(PathID_t id) const
|
2018-08-10 23:34:11 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-08-10 23:34:11 +02:00
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->RXID() == id)
|
|
|
|
return itr->second;
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-11-16 15:06:50 +01:00
|
|
|
size_t
|
|
|
|
PathSet::AvailablePaths(PathRole roles) const
|
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-11-16 15:06:50 +01:00
|
|
|
size_t count = 0;
|
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->Status() == ePathEstablished
|
2018-11-21 13:31:36 +01:00
|
|
|
&& itr->second->SupportsAnyRoles(roles))
|
2018-11-16 15:06:50 +01:00
|
|
|
++count;
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2018-06-25 17:12:08 +02:00
|
|
|
size_t
|
|
|
|
PathSet::NumInStatus(PathStatus st) const
|
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-06-25 17:12:08 +02:00
|
|
|
size_t count = 0;
|
2018-06-26 16:52:19 +02:00
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
2018-06-25 17:12:08 +02:00
|
|
|
{
|
2018-11-14 19:02:27 +01:00
|
|
|
if(itr->second->Status() == st)
|
2018-06-25 17:12:08 +02:00
|
|
|
++count;
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-04-23 16:28:59 +02:00
|
|
|
PathSet::AddPath(Path_ptr path)
|
2018-06-25 17:12:08 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-11-03 14:19:18 +01:00
|
|
|
auto upstream = path->Upstream(); // RouterID
|
|
|
|
auto RXID = path->RXID(); // PathID
|
2019-04-23 16:28:59 +02:00
|
|
|
m_Paths.emplace(std::make_pair(upstream, RXID), std::move(path));
|
2018-06-25 17:12:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-04-23 16:28:59 +02:00
|
|
|
PathSet::RemovePath(Path_ptr path)
|
2018-06-25 17:12:08 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-06-26 16:52:19 +02:00
|
|
|
m_Paths.erase({path->Upstream(), path->RXID()});
|
2018-06-25 17:12:08 +02:00
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2018-12-18 19:36:19 +01:00
|
|
|
PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const
|
2018-06-25 17:12:08 +02:00
|
|
|
{
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-06-26 16:52:19 +02:00
|
|
|
auto itr = m_Paths.find({remote, rxid});
|
|
|
|
if(itr == m_Paths.end())
|
|
|
|
return nullptr;
|
|
|
|
return itr->second;
|
2018-06-25 17:12:08 +02:00
|
|
|
}
|
|
|
|
|
2018-10-01 16:18:17 +02:00
|
|
|
bool
|
|
|
|
PathSet::GetCurrentIntroductionsWithFilter(
|
2019-02-18 11:35:16 +01:00
|
|
|
std::set< service::Introduction >& intros,
|
|
|
|
std::function< bool(const service::Introduction&) > filter) const
|
2018-10-01 16:18:17 +02:00
|
|
|
{
|
|
|
|
intros.clear();
|
|
|
|
size_t count = 0;
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-12-02 19:07:07 +01:00
|
|
|
auto itr = m_Paths.begin();
|
2018-10-01 16:18:17 +02:00
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->IsReady() && filter(itr->second->intro))
|
|
|
|
{
|
|
|
|
intros.insert(itr->second->intro);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return count > 0;
|
|
|
|
}
|
|
|
|
|
2018-07-09 19:32:11 +02:00
|
|
|
bool
|
2018-07-11 18:11:19 +02:00
|
|
|
PathSet::GetCurrentIntroductions(
|
2019-02-18 11:35:16 +01:00
|
|
|
std::set< service::Introduction >& intros) const
|
2018-07-11 18:11:19 +02:00
|
|
|
{
|
2018-07-17 08:17:13 +02:00
|
|
|
intros.clear();
|
2018-07-11 18:11:19 +02:00
|
|
|
size_t count = 0;
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-12-02 19:07:07 +01:00
|
|
|
auto itr = m_Paths.begin();
|
2018-07-11 18:11:19 +02:00
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->IsReady())
|
|
|
|
{
|
2018-07-19 06:58:39 +02:00
|
|
|
intros.insert(itr->second->intro);
|
2018-07-11 18:11:19 +02:00
|
|
|
++count;
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return count > 0;
|
|
|
|
}
|
|
|
|
|
2018-09-26 15:04:25 +02:00
|
|
|
void
|
2019-04-23 16:28:59 +02:00
|
|
|
PathSet::HandlePathBuildTimeout(Path_ptr p)
|
2018-09-26 15:04:25 +02:00
|
|
|
{
|
2019-05-05 15:51:48 +02:00
|
|
|
LogWarn(Name(), " path build ", p->HopsString(), " timed out");
|
2019-07-01 15:44:25 +02:00
|
|
|
m_BuildStats.timeouts++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathSet::PathBuildStarted(Path_ptr p)
|
|
|
|
{
|
|
|
|
LogInfo(Name(), " path build ", p->HopsString(), " started");
|
|
|
|
m_BuildStats.attempts++;
|
|
|
|
}
|
|
|
|
|
|
|
|
util::StatusObject
|
|
|
|
BuildStats::ExtractStatus() const
|
|
|
|
{
|
|
|
|
return util::StatusObject{{"success", success},
|
|
|
|
{"attempts", attempts},
|
|
|
|
{"timeouts", timeouts},
|
|
|
|
{"fails", fails}};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
|
|
|
BuildStats::ToString() const
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
2019-07-01 16:56:56 +02:00
|
|
|
ss << (SuccsessRatio() * 100.0) << " percent success ";
|
2019-07-01 15:44:25 +02:00
|
|
|
ss << "(success=" << success << " ";
|
|
|
|
ss << "attempts=" << attempts << " ";
|
|
|
|
ss << "timeouts=" << timeouts << " ";
|
|
|
|
ss << "fails=" << fails << ")";
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
double
|
|
|
|
BuildStats::SuccsessRatio() const
|
|
|
|
{
|
|
|
|
if(attempts)
|
2019-07-01 16:56:56 +02:00
|
|
|
return double(success) / double(attempts);
|
|
|
|
return 0.0;
|
2018-09-26 15:04:25 +02:00
|
|
|
}
|
|
|
|
|
2018-09-27 12:51:30 +02:00
|
|
|
bool
|
|
|
|
PathSet::GetNewestIntro(service::Introduction& intro) const
|
|
|
|
{
|
2018-09-27 13:03:01 +02:00
|
|
|
intro.Clear();
|
2018-09-27 12:51:30 +02:00
|
|
|
bool found = false;
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-12-02 19:07:07 +01:00
|
|
|
auto itr = m_Paths.begin();
|
2018-09-27 12:51:30 +02:00
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->IsReady()
|
|
|
|
&& itr->second->intro.expiresAt > intro.expiresAt)
|
|
|
|
{
|
|
|
|
intro = itr->second->intro;
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2019-04-23 16:28:59 +02:00
|
|
|
Path_ptr
|
2018-11-14 19:02:27 +01:00
|
|
|
PathSet::PickRandomEstablishedPath(PathRole roles) const
|
2018-07-11 18:11:19 +02:00
|
|
|
{
|
2019-04-23 16:28:59 +02:00
|
|
|
std::vector< Path_ptr > established;
|
2019-03-03 16:01:05 +01:00
|
|
|
Lock_t l(&m_PathsMutex);
|
2018-07-11 18:11:19 +02:00
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
2018-11-21 13:31:36 +01:00
|
|
|
if(itr->second->IsReady() && itr->second->SupportsAnyRoles(roles))
|
2018-07-11 18:11:19 +02:00
|
|
|
established.push_back(itr->second);
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
auto sz = established.size();
|
|
|
|
if(sz)
|
|
|
|
{
|
2019-02-18 11:35:16 +01:00
|
|
|
return established[randint() % sz];
|
2018-07-11 18:11:19 +02:00
|
|
|
}
|
2019-07-06 19:03:40 +02:00
|
|
|
|
|
|
|
return nullptr;
|
2018-07-11 18:11:19 +02:00
|
|
|
}
|
|
|
|
|
2018-06-25 17:12:08 +02:00
|
|
|
} // namespace path
|
2018-08-17 21:49:58 +02:00
|
|
|
} // namespace llarp
|