2019-06-17 23:19:39 +00:00
|
|
|
#include <path/path_context.hpp>
|
|
|
|
|
|
|
|
#include <messages/relay_commit.hpp>
|
|
|
|
#include <path/path.hpp>
|
|
|
|
#include <router/abstractrouter.hpp>
|
2019-06-04 18:31:17 +00:00
|
|
|
#include <router/i_outbound_message_handler.hpp>
|
2019-06-17 23:19:39 +00:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace path
|
|
|
|
{
|
2020-02-24 15:26:46 +00:00
|
|
|
static constexpr auto DefaultPathBuildLimit = 500ms;
|
2019-12-30 22:03:34 +00:00
|
|
|
|
2019-06-17 23:19:39 +00:00
|
|
|
PathContext::PathContext(AbstractRouter* router)
|
2020-04-07 18:38:56 +00:00
|
|
|
: m_Router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathContext::AllowTransit()
|
|
|
|
{
|
|
|
|
m_AllowTransit = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
PathContext::AllowingTransit() const
|
|
|
|
{
|
|
|
|
return m_AllowTransit;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
std::shared_ptr<thread::ThreadPool>
|
2019-06-17 23:19:39 +00:00
|
|
|
PathContext::Worker()
|
|
|
|
{
|
|
|
|
return m_Router->threadpool();
|
|
|
|
}
|
|
|
|
|
2019-12-30 20:15:19 +00:00
|
|
|
bool
|
2020-05-06 20:38:44 +00:00
|
|
|
PathContext::CheckPathLimitHitByIP(const IpAddress& ip)
|
2019-12-30 20:15:19 +00:00
|
|
|
{
|
2020-01-14 01:01:33 +00:00
|
|
|
#ifdef TESTNET
|
|
|
|
return false;
|
|
|
|
#else
|
2020-05-06 20:38:44 +00:00
|
|
|
IpAddress remote = ip;
|
|
|
|
// null out the port -- we don't care about it for path limiting purposes
|
|
|
|
remote.setPort(0);
|
2019-12-30 20:55:56 +00:00
|
|
|
// try inserting remote address by ip into decaying hash set
|
|
|
|
// if it cannot insert it has hit a limit
|
2020-02-25 22:37:15 +00:00
|
|
|
return not m_PathLimits.Insert(remote);
|
2020-01-14 01:01:33 +00:00
|
|
|
#endif
|
2019-12-30 20:15:19 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
std::shared_ptr<Logic>
|
2019-06-17 23:19:39 +00:00
|
|
|
PathContext::logic()
|
|
|
|
{
|
|
|
|
return m_Router->logic();
|
|
|
|
}
|
|
|
|
|
|
|
|
const SecretKey&
|
|
|
|
PathContext::EncryptionSecretKey()
|
|
|
|
{
|
|
|
|
return m_Router->encryption();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
PathContext::HopIsUs(const RouterID& k) const
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
return std::equal(m_Router->pubkey(), m_Router->pubkey() + PUBKEYSIZE, k.begin());
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PathContext::EndpointPathPtrSet
|
|
|
|
PathContext::FindOwnedPathsWithEndpoint(const RouterID& r)
|
|
|
|
{
|
|
|
|
EndpointPathPtrSet found;
|
2019-12-03 15:52:06 +00:00
|
|
|
m_OurPaths.ForEach([&](const Path_ptr& p) {
|
2020-04-07 18:38:56 +00:00
|
|
|
if (p->Endpoint() == r && p->IsReady())
|
2019-12-03 15:52:06 +00:00
|
|
|
found.insert(p);
|
2019-06-17 23:19:39 +00:00
|
|
|
});
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
PathContext::ForwardLRCM(
|
|
|
|
const RouterID& nextHop,
|
|
|
|
const std::array<EncryptedFrame, 8>& frames,
|
|
|
|
SendStatusHandler handler)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (handler == nullptr)
|
2019-06-04 18:31:17 +00:00
|
|
|
{
|
|
|
|
LogError("Calling ForwardLRCM without passing result handler");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
auto msg = std::make_shared<const LR_CommitMessage>(frames);
|
2019-06-17 23:19:39 +00:00
|
|
|
|
|
|
|
LogDebug("forwarding LRCM to ", nextHop);
|
2019-06-04 18:31:17 +00:00
|
|
|
|
|
|
|
m_Router->SendToOrQueue(nextHop, msg.get(), handler);
|
|
|
|
|
2019-06-17 23:19:39 +00:00
|
|
|
return true;
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
template <
|
|
|
|
typename Lock_t,
|
|
|
|
typename Map_t,
|
|
|
|
typename Key_t,
|
|
|
|
typename CheckValue_t,
|
|
|
|
typename GetFunc_t>
|
2019-06-17 23:19:39 +00:00
|
|
|
HopHandler_ptr
|
|
|
|
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
Lock_t lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto range = map.second.equal_range(k);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto i = range.first; i != range.second; ++i)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (check(i->second))
|
2019-06-17 23:19:39 +00:00
|
|
|
return get(i->second);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
template <typename Lock_t, typename Map_t, typename Key_t, typename CheckValue_t>
|
2019-06-17 23:19:39 +00:00
|
|
|
bool
|
|
|
|
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
Lock_t lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto range = map.second.equal_range(k);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto i = range.first; i != range.second; ++i)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (check(i->second))
|
2019-06-17 23:19:39 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
template <typename Lock_t, typename Map_t, typename Key_t, typename Value_t>
|
2019-06-17 23:19:39 +00:00
|
|
|
void
|
|
|
|
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
Lock_t lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
map.second.emplace(k, v);
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
template <typename Lock_t, typename Map_t, typename Visit_t>
|
2019-06-17 23:19:39 +00:00
|
|
|
void
|
|
|
|
MapIter(Map_t& map, Visit_t v)
|
|
|
|
{
|
2019-09-04 12:41:07 +00:00
|
|
|
Lock_t lock(map.first);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& item : map.second)
|
2019-06-17 23:19:39 +00:00
|
|
|
v(item);
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
template <typename Lock_t, typename Map_t, typename Key_t, typename Check_t>
|
2019-06-17 23:19:39 +00:00
|
|
|
void
|
|
|
|
MapDel(Map_t& map, const Key_t& k, Check_t check)
|
|
|
|
{
|
2019-09-04 12:41:07 +00:00
|
|
|
Lock_t lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto range = map.second.equal_range(k);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto i = range.first; i != range.second;)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (check(i->second))
|
2019-06-17 23:19:39 +00:00
|
|
|
i = map.second.erase(i);
|
|
|
|
else
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path)
|
|
|
|
{
|
|
|
|
set->AddPath(path);
|
2020-04-07 18:38:56 +00:00
|
|
|
MapPut<util::Lock>(m_OurPaths, path->TXID(), path);
|
|
|
|
MapPut<util::Lock>(m_OurPaths, path->RXID(), path);
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
PathContext::HasTransitHop(const TransitHopInfo& info)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
return MapHas<SyncTransitMap_t::Lock_t>(
|
|
|
|
m_TransitPaths, info.txID, [info](const std::shared_ptr<TransitHop>& hop) -> bool {
|
2019-09-04 12:41:07 +00:00
|
|
|
return info == hop->info;
|
|
|
|
});
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HopHandler_ptr
|
|
|
|
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
auto own = MapGet<util::Lock>(
|
|
|
|
m_OurPaths,
|
|
|
|
id,
|
2019-12-03 15:52:06 +00:00
|
|
|
[](const Path_ptr) -> bool {
|
2019-08-13 21:38:00 +00:00
|
|
|
// TODO: is this right?
|
|
|
|
return true;
|
|
|
|
},
|
2019-12-03 15:52:06 +00:00
|
|
|
[](Path_ptr p) -> HopHandler_ptr { return p; });
|
2020-04-07 18:38:56 +00:00
|
|
|
if (own)
|
2019-06-17 23:19:39 +00:00
|
|
|
return own;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
return MapGet<SyncTransitMap_t::Lock_t>(
|
|
|
|
m_TransitPaths,
|
|
|
|
id,
|
|
|
|
[remote](const std::shared_ptr<TransitHop>& hop) -> bool {
|
2019-06-17 23:19:39 +00:00
|
|
|
return hop->info.upstream == remote;
|
|
|
|
},
|
2020-04-07 18:38:56 +00:00
|
|
|
[](const std::shared_ptr<TransitHop>& h) -> HopHandler_ptr { return h; });
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
PathContext::TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& otherRouter)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
SyncTransitMap_t::Lock_t lock(m_TransitPaths.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto itr = m_TransitPaths.second.find(path);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (itr == m_TransitPaths.second.end())
|
2019-06-17 23:19:39 +00:00
|
|
|
return false;
|
|
|
|
return itr->second->info.downstream == otherRouter;
|
|
|
|
}
|
|
|
|
|
|
|
|
HopHandler_ptr
|
|
|
|
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
return MapGet<SyncTransitMap_t::Lock_t>(
|
|
|
|
m_TransitPaths,
|
|
|
|
id,
|
|
|
|
[remote](const std::shared_ptr<TransitHop>& hop) -> bool {
|
2019-06-17 23:19:39 +00:00
|
|
|
return hop->info.downstream == remote;
|
|
|
|
},
|
2020-04-07 18:38:56 +00:00
|
|
|
[](const std::shared_ptr<TransitHop>& h) -> HopHandler_ptr { return h; });
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PathSet_ptr
|
|
|
|
PathContext::GetLocalPathSet(const PathID_t& id)
|
|
|
|
{
|
|
|
|
auto& map = m_OurPaths;
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
util::Lock lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto itr = map.second.find(id);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (itr != map.second.end())
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2019-12-03 15:52:06 +00:00
|
|
|
return itr->second->m_PathSet->GetSelf();
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const byte_t*
|
|
|
|
PathContext::OurRouterID() const
|
|
|
|
{
|
|
|
|
return m_Router->pubkey();
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractRouter*
|
|
|
|
PathContext::Router()
|
|
|
|
{
|
|
|
|
return m_Router;
|
|
|
|
}
|
|
|
|
|
2019-11-21 14:48:31 +00:00
|
|
|
TransitHop_ptr
|
2019-06-17 23:19:39 +00:00
|
|
|
PathContext::GetPathForTransfer(const PathID_t& id)
|
|
|
|
{
|
2019-11-21 14:48:31 +00:00
|
|
|
const RouterID us(OurRouterID());
|
2019-06-17 23:19:39 +00:00
|
|
|
auto& map = m_TransitPaths;
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
SyncTransitMap_t::Lock_t lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto range = map.second.equal_range(id);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto i = range.first; i != range.second; ++i)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (i->second->info.upstream == us)
|
2019-06-17 23:19:39 +00:00
|
|
|
return i->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-09-05 17:39:09 +00:00
|
|
|
void
|
2019-09-16 10:21:12 +00:00
|
|
|
PathContext::PumpUpstream()
|
2019-09-05 17:39:09 +00:00
|
|
|
{
|
2019-09-16 10:21:12 +00:00
|
|
|
m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); });
|
2019-12-03 15:52:06 +00:00
|
|
|
m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); });
|
2019-09-16 10:21:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathContext::PumpDownstream()
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); });
|
2019-12-03 15:52:06 +00:00
|
|
|
m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); });
|
2019-09-05 17:39:09 +00:00
|
|
|
}
|
|
|
|
|
2020-03-03 23:04:09 +00:00
|
|
|
uint64_t
|
|
|
|
PathContext::CurrentTransitPaths()
|
|
|
|
{
|
2020-03-03 23:16:08 +00:00
|
|
|
SyncTransitMap_t::Lock_t lock(m_TransitPaths.first);
|
|
|
|
auto& map = m_TransitPaths.second;
|
|
|
|
return map.size() / 2;
|
2020-03-03 23:04:09 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 23:19:39 +00:00
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
PathContext::PutTransitHop(std::shared_ptr<TransitHop> hop)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
MapPut<SyncTransitMap_t::Lock_t>(m_TransitPaths, hop->info.txID, hop);
|
|
|
|
MapPut<SyncTransitMap_t::Lock_t>(m_TransitPaths, hop->info.rxID, hop);
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PathContext::ExpirePaths(llarp_time_t now)
|
|
|
|
{
|
2019-12-30 20:58:30 +00:00
|
|
|
// decay limits
|
2020-02-25 17:05:13 +00:00
|
|
|
m_PathLimits.Decay(now);
|
2019-12-30 20:15:19 +00:00
|
|
|
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
SyncTransitMap_t::Lock_t lock(m_TransitPaths.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto& map = m_TransitPaths.second;
|
2020-04-07 18:38:56 +00:00
|
|
|
auto itr = map.begin();
|
|
|
|
while (itr != map.end())
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-05-21 14:23:54 +00:00
|
|
|
itr->second->DecayFilters(now);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (itr->second->Expired(now))
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2019-10-25 21:13:11 +00:00
|
|
|
m_Router->outboundMessageHandler().QueueRemoveEmptyPath(itr->first);
|
2019-06-17 23:19:39 +00:00
|
|
|
itr = map.erase(itr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2019-12-03 15:52:06 +00:00
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
util::Lock lock(m_OurPaths.first);
|
2019-12-03 15:52:06 +00:00
|
|
|
auto& map = m_OurPaths.second;
|
2020-04-07 18:38:56 +00:00
|
|
|
auto itr = map.begin();
|
|
|
|
while (itr != map.end())
|
2019-12-03 15:52:06 +00:00
|
|
|
{
|
2020-05-21 14:23:54 +00:00
|
|
|
itr->second->DecayFilters(now);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (itr->second->Expired(now))
|
2019-12-03 15:52:06 +00:00
|
|
|
{
|
|
|
|
itr = map.erase(itr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2019-06-17 23:19:39 +00:00
|
|
|
}
|
2019-11-05 16:58:53 +00:00
|
|
|
|
2019-06-17 23:19:39 +00:00
|
|
|
routing::MessageHandler_ptr
|
|
|
|
PathContext::GetHandler(const PathID_t& id)
|
|
|
|
{
|
|
|
|
routing::MessageHandler_ptr h = nullptr;
|
2020-04-07 18:38:56 +00:00
|
|
|
auto pathset = GetLocalPathSet(id);
|
|
|
|
if (pathset)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
|
|
|
h = pathset->GetPathByID(id);
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
if (h)
|
2019-06-17 23:19:39 +00:00
|
|
|
return h;
|
|
|
|
const RouterID us(OurRouterID());
|
|
|
|
auto& map = m_TransitPaths;
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 17:21:11 +00:00
|
|
|
SyncTransitMap_t::Lock_t lock(map.first);
|
2019-06-17 23:19:39 +00:00
|
|
|
auto range = map.second.equal_range(id);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto i = range.first; i != range.second; ++i)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (i->second->info.upstream == us)
|
2019-06-17 23:19:39 +00:00
|
|
|
return i->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-12-03 15:52:06 +00:00
|
|
|
void PathContext::RemovePathSet(PathSet_ptr)
|
2019-06-17 23:19:39 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
} // namespace path
|
|
|
|
} // namespace llarp
|