lokinet/llarp/path/pathset.cpp

339 lines
7.7 KiB
C++
Raw Normal View History

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>
#include <messages/dht.hpp>
2019-01-11 02:19:36 +01:00
#include <path/path.hpp>
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
{
2019-04-22 21:15:07 +02:00
(void) now;
const auto building = NumInStatus(ePathBuilding);
if(building > m_NumPaths)
return false;
const auto established = NumInStatus(ePathEstablished);
return established <= m_NumPaths;
}
2018-11-14 19:02:27 +01:00
bool
PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const
{
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;
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
{
if(!item.second->Expired(futureTime))
++num;
}
return num;
}
void
PathSet::Tick(llarp_time_t now, AbstractRouter* r)
{
Lock_t l(&m_PathsMutex);
for(auto& item : m_Paths)
{
item.second->Tick(now, r);
}
}
void
PathSet::ExpirePaths(llarp_time_t now)
{
Lock_t l(&m_PathsMutex);
if(m_Paths.size() == 0)
return;
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->Expired(now))
{
delete itr->second;
itr = m_Paths.erase(itr);
}
else
++itr;
}
}
2018-07-23 01:14:29 +02:00
Path*
2018-12-18 19:36:19 +01:00
PathSet::GetEstablishedPathClosestTo(RouterID id, PathRole roles) const
2018-08-02 00:10:38 +02:00
{
Lock_t l(&m_PathsMutex);
2018-08-02 00:10:38 +02:00
Path* path = nullptr;
AlignedBuffer< 32 > dist;
AlignedBuffer< 32 > to = id;
2018-08-02 00:10:38 +02:00
dist.Fill(0xff);
for(const auto& item : m_Paths)
{
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;
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;
}
Path*
2018-12-18 19:36:19 +01:00
PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const
{
Lock_t l(&m_PathsMutex);
Path* chosen = nullptr;
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))
{
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;
}
2018-08-02 00:10:38 +02:00
Path*
2018-12-18 19:36:19 +01:00
PathSet::GetPathByRouter(RouterID id, PathRole roles) const
2018-07-23 01:14:29 +02:00
{
Lock_t l(&m_PathsMutex);
Path* chosen = nullptr;
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))
{
if(itr->second->Endpoint() == id)
{
if(chosen == nullptr)
chosen = itr->second;
else if(chosen->intro.latency > itr->second->intro.latency)
chosen = itr->second;
}
}
2018-07-23 01:14:29 +02:00
++itr;
}
return chosen;
2018-07-23 01:14:29 +02:00
}
2019-03-08 18:26:29 +01:00
Path*
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;
}
2018-08-10 23:34:11 +02:00
Path*
2018-12-18 19:36:19 +01:00
PathSet::GetPathByID(PathID_t id) const
2018-08-10 23:34:11 +02: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
{
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;
}
size_t
PathSet::NumInStatus(PathStatus st) const
{
Lock_t l(&m_PathsMutex);
size_t count = 0;
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
2018-11-14 19:02:27 +01:00
if(itr->second->Status() == st)
++count;
++itr;
}
return count;
}
void
PathSet::AddPath(Path* path)
{
Lock_t l(&m_PathsMutex);
2018-11-03 14:19:18 +01:00
auto upstream = path->Upstream(); // RouterID
auto RXID = path->RXID(); // PathID
m_Paths.emplace(std::make_pair(upstream, RXID), path);
}
void
PathSet::RemovePath(Path* path)
{
Lock_t l(&m_PathsMutex);
m_Paths.erase({path->Upstream(), path->RXID()});
}
Path*
2018-12-18 19:36:19 +01:00
PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const
{
Lock_t l(&m_PathsMutex);
auto itr = m_Paths.find({remote, rxid});
if(itr == m_Paths.end())
return nullptr;
return itr->second;
}
bool
PathSet::GetCurrentIntroductionsWithFilter(
std::set< service::Introduction >& intros,
std::function< bool(const service::Introduction&) > filter) const
{
intros.clear();
size_t count = 0;
Lock_t l(&m_PathsMutex);
auto itr = m_Paths.begin();
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
PathSet::GetCurrentIntroductions(
std::set< service::Introduction >& intros) const
{
2018-07-17 08:17:13 +02:00
intros.clear();
size_t count = 0;
Lock_t l(&m_PathsMutex);
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->IsReady())
{
2018-07-19 06:58:39 +02:00
intros.insert(itr->second->intro);
++count;
}
++itr;
}
return count > 0;
}
void
PathSet::HandlePathBuildTimeout(Path* p)
{
2019-03-22 15:10:30 +01:00
LogInfo(Name(), " path build ", p->HopsString(), " timed out");
}
bool
PathSet::GetNewestIntro(service::Introduction& intro) const
{
2018-09-27 13:03:01 +02:00
intro.Clear();
bool found = false;
Lock_t l(&m_PathsMutex);
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->IsReady()
&& itr->second->intro.expiresAt > intro.expiresAt)
{
intro = itr->second->intro;
found = true;
}
++itr;
}
return found;
}
Path*
2018-11-14 19:02:27 +01:00
PathSet::PickRandomEstablishedPath(PathRole roles) const
{
std::vector< Path* > established;
Lock_t l(&m_PathsMutex);
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))
established.push_back(itr->second);
++itr;
}
auto sz = established.size();
if(sz)
{
return established[randint() % sz];
}
else
return nullptr;
}
} // namespace path
} // namespace llarp