2018-07-11 16:11:19 +00:00
|
|
|
#include <llarp/dht/messages/pubintro.hpp>
|
|
|
|
#include <llarp/messages/dht.hpp>
|
2018-06-25 15:12:08 +00:00
|
|
|
#include <llarp/path.hpp>
|
|
|
|
#include <llarp/pathset.hpp>
|
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace path
|
|
|
|
{
|
|
|
|
PathSet::PathSet(size_t num) : m_NumPaths(num)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-10-29 16:48:36 +00:00
|
|
|
PathSet::ShouldBuildMore(llarp_time_t now) const
|
2018-06-25 15:12:08 +00:00
|
|
|
{
|
2018-10-29 16:48:36 +00:00
|
|
|
(void)now;
|
2018-06-26 14:52:19 +00:00
|
|
|
return m_Paths.size() < m_NumPaths;
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 18:02:27 +00:00
|
|
|
bool
|
|
|
|
PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const
|
|
|
|
{
|
|
|
|
const size_t required = MinRequiredForRoles(roles);
|
|
|
|
size_t has = 0;
|
|
|
|
for(const auto& item : m_Paths)
|
|
|
|
{
|
|
|
|
if(item.second->SupportsRoles(roles))
|
|
|
|
{
|
|
|
|
if(!item.second->ExpiresSoon(now))
|
|
|
|
++has;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return has < required;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
PathSet::MinRequiredForRoles(PathRole roles) const
|
|
|
|
{
|
|
|
|
size_t require = m_NumPaths > 1 ? m_NumPaths / 2 : m_NumPaths;
|
|
|
|
if(roles & ePathRoleInboundHS || roles & ePathRoleOutboundHS)
|
|
|
|
require += 2;
|
|
|
|
return require;
|
|
|
|
}
|
|
|
|
|
2018-06-29 16:02:39 +00:00
|
|
|
void
|
|
|
|
PathSet::Tick(llarp_time_t now, llarp_router* r)
|
|
|
|
{
|
|
|
|
for(auto& item : m_Paths)
|
|
|
|
{
|
2018-09-13 16:41:53 +00:00
|
|
|
item.second->Tick(now, r);
|
2018-06-29 16:02:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 15:12:08 +00:00
|
|
|
void
|
|
|
|
PathSet::ExpirePaths(llarp_time_t now)
|
|
|
|
{
|
2018-08-17 19:49:58 +00:00
|
|
|
if(m_Paths.size() == 0)
|
|
|
|
return;
|
2018-06-26 14:52:19 +00:00
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
2018-06-25 15:12:08 +00:00
|
|
|
{
|
2018-06-26 14:52:19 +00:00
|
|
|
if(itr->second->Expired(now))
|
2018-06-25 15:12:08 +00:00
|
|
|
{
|
2018-06-26 14:52:19 +00:00
|
|
|
delete itr->second;
|
|
|
|
itr = m_Paths.erase(itr);
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
2018-06-26 14:52:19 +00:00
|
|
|
else
|
|
|
|
++itr;
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-22 23:14:29 +00:00
|
|
|
Path*
|
2018-11-14 18:02:27 +00:00
|
|
|
PathSet::GetEstablishedPathClosestTo(const AlignedBuffer< 32 >& id,
|
|
|
|
PathRole roles) const
|
2018-08-01 22:10:38 +00:00
|
|
|
{
|
|
|
|
Path* path = nullptr;
|
2018-08-02 00:48:43 +00:00
|
|
|
AlignedBuffer< 32 > dist;
|
2018-08-01 22:10:38 +00:00
|
|
|
dist.Fill(0xff);
|
|
|
|
for(const auto& item : m_Paths)
|
|
|
|
{
|
2018-08-02 00:48:43 +00:00
|
|
|
if(!item.second->IsReady())
|
|
|
|
continue;
|
2018-11-14 18:02:27 +00:00
|
|
|
if(!item.second->SupportsRoles(roles))
|
|
|
|
continue;
|
2018-08-02 00:48:43 +00:00
|
|
|
AlignedBuffer< 32 > localDist = item.second->Endpoint() ^ id;
|
2018-08-01 22:10:38 +00:00
|
|
|
if(localDist < dist)
|
|
|
|
{
|
|
|
|
dist = localDist;
|
|
|
|
path = item.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2018-09-18 23:56:26 +00:00
|
|
|
Path*
|
2018-11-14 18:02:27 +00:00
|
|
|
PathSet::GetNewestPathByRouter(const RouterID& id, PathRole roles) const
|
2018-09-18 23:56:26 +00:00
|
|
|
{
|
|
|
|
Path* chosen = nullptr;
|
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
2018-11-14 18:02:27 +00:00
|
|
|
if(itr->second->IsReady() && itr->second->SupportsRoles(roles))
|
2018-09-18 23:56:26 +00: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;
|
|
|
|
}
|
|
|
|
|
2018-08-01 22:10:38 +00:00
|
|
|
Path*
|
2018-11-14 18:02:27 +00:00
|
|
|
PathSet::GetPathByRouter(const RouterID& id, PathRole roles) const
|
2018-07-22 23:14:29 +00:00
|
|
|
{
|
2018-09-13 16:41:53 +00:00
|
|
|
Path* chosen = nullptr;
|
|
|
|
auto itr = m_Paths.begin();
|
2018-07-22 23:14:29 +00:00
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
2018-11-14 18:02:27 +00:00
|
|
|
if(itr->second->IsReady() && itr->second->SupportsRoles(roles))
|
2018-07-23 07:38:29 +00:00
|
|
|
{
|
|
|
|
if(itr->second->Endpoint() == id)
|
2018-09-13 16:41:53 +00:00
|
|
|
{
|
|
|
|
if(chosen == nullptr)
|
|
|
|
chosen = itr->second;
|
|
|
|
else if(chosen->intro.latency > itr->second->intro.latency)
|
|
|
|
chosen = itr->second;
|
|
|
|
}
|
2018-07-23 07:38:29 +00:00
|
|
|
}
|
2018-07-22 23:14:29 +00:00
|
|
|
++itr;
|
|
|
|
}
|
2018-09-13 16:41:53 +00:00
|
|
|
return chosen;
|
2018-07-22 23:14:29 +00:00
|
|
|
}
|
|
|
|
|
2018-08-10 21:34:11 +00:00
|
|
|
Path*
|
|
|
|
PathSet::GetPathByID(const PathID_t& id) const
|
|
|
|
{
|
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->RXID() == id)
|
|
|
|
return itr->second;
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-06-25 15:12:08 +00:00
|
|
|
size_t
|
|
|
|
PathSet::NumInStatus(PathStatus st) const
|
|
|
|
{
|
|
|
|
size_t count = 0;
|
2018-06-26 14:52:19 +00:00
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
2018-06-25 15:12:08 +00:00
|
|
|
{
|
2018-11-14 18:02:27 +00:00
|
|
|
if(itr->second->Status() == st)
|
2018-06-25 15:12:08 +00:00
|
|
|
++count;
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathSet::AddPath(Path* path)
|
|
|
|
{
|
2018-11-03 13:19:18 +00:00
|
|
|
auto upstream = path->Upstream(); // RouterID
|
|
|
|
auto RXID = path->RXID(); // PathID
|
|
|
|
m_Paths.insert(std::make_pair(std::make_pair(upstream, RXID), path));
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathSet::RemovePath(Path* path)
|
|
|
|
{
|
2018-06-26 14:52:19 +00:00
|
|
|
m_Paths.erase({path->Upstream(), path->RXID()});
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Path*
|
2018-08-01 22:10:38 +00:00
|
|
|
PathSet::GetByUpstream(const RouterID& remote, const PathID_t& rxid) const
|
2018-06-25 15:12:08 +00:00
|
|
|
{
|
2018-06-26 14:52:19 +00:00
|
|
|
auto itr = m_Paths.find({remote, rxid});
|
|
|
|
if(itr == m_Paths.end())
|
|
|
|
return nullptr;
|
|
|
|
return itr->second;
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathSet::HandlePathBuilt(Path* path)
|
|
|
|
{
|
2018-10-29 16:48:36 +00:00
|
|
|
auto dlt = Now() - path->buildStarted;
|
2018-07-05 15:44:06 +00:00
|
|
|
llarp::LogInfo("Path build took ", dlt, "ms for tx=", path->TXID(),
|
|
|
|
" rx=", path->RXID());
|
2018-06-25 15:12:08 +00:00
|
|
|
}
|
|
|
|
|
2018-10-01 14:18:17 +00:00
|
|
|
bool
|
|
|
|
PathSet::GetCurrentIntroductionsWithFilter(
|
|
|
|
std::set< llarp::service::Introduction >& intros,
|
|
|
|
std::function< bool(const llarp::service::Introduction&) > filter) const
|
|
|
|
{
|
|
|
|
intros.clear();
|
|
|
|
size_t count = 0;
|
|
|
|
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 17:32:11 +00:00
|
|
|
bool
|
2018-07-11 16:11:19 +00:00
|
|
|
PathSet::GetCurrentIntroductions(
|
2018-07-19 04:58:39 +00:00
|
|
|
std::set< llarp::service::Introduction >& intros) const
|
2018-07-11 16:11:19 +00:00
|
|
|
{
|
2018-07-17 06:17:13 +00:00
|
|
|
intros.clear();
|
2018-07-11 16:11:19 +00:00
|
|
|
size_t count = 0;
|
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
|
|
|
if(itr->second->IsReady())
|
|
|
|
{
|
2018-07-19 04:58:39 +00:00
|
|
|
intros.insert(itr->second->intro);
|
2018-07-11 16:11:19 +00:00
|
|
|
++count;
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return count > 0;
|
|
|
|
}
|
|
|
|
|
2018-09-26 13:04:25 +00:00
|
|
|
void
|
|
|
|
PathSet::HandlePathBuildTimeout(Path* p)
|
|
|
|
{
|
|
|
|
llarp::LogInfo("path ", p->Name(), " has timed out");
|
|
|
|
}
|
|
|
|
|
2018-09-27 10:51:30 +00:00
|
|
|
bool
|
|
|
|
PathSet::GetNewestIntro(service::Introduction& intro) const
|
|
|
|
{
|
2018-09-27 11:03:01 +00:00
|
|
|
intro.Clear();
|
2018-09-27 10:51:30 +00:00
|
|
|
bool found = false;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-07-11 16:11:19 +00:00
|
|
|
Path*
|
2018-11-14 18:02:27 +00:00
|
|
|
PathSet::PickRandomEstablishedPath(PathRole roles) const
|
2018-07-11 16:11:19 +00:00
|
|
|
{
|
|
|
|
std::vector< Path* > established;
|
|
|
|
auto itr = m_Paths.begin();
|
|
|
|
while(itr != m_Paths.end())
|
|
|
|
{
|
2018-11-14 18:02:27 +00:00
|
|
|
if(itr->second->IsReady() && itr->second->SupportsRoles(roles))
|
2018-07-11 16:11:19 +00:00
|
|
|
established.push_back(itr->second);
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
auto sz = established.size();
|
|
|
|
if(sz)
|
|
|
|
{
|
2018-07-20 04:50:28 +00:00
|
|
|
return established[llarp_randint() % sz];
|
2018-07-11 16:11:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-06-25 15:12:08 +00:00
|
|
|
} // namespace path
|
2018-08-17 19:49:58 +00:00
|
|
|
} // namespace llarp
|