2019-06-26 21:39:29 +00:00
|
|
|
#include <link/link_manager.hpp>
|
|
|
|
|
|
|
|
#include <router/i_outbound_session_maker.hpp>
|
|
|
|
#include <crypto/crypto.hpp>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <set>
|
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
LinkLayer_ptr
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::GetCompatibleLink(const RouterContact& rc) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return nullptr;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
// TODO: may want to add some memory of session failures for a given
|
|
|
|
// router on a given link and not return that link here for a
|
|
|
|
// duration
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!link->IsCompatable(rc))
|
2019-06-26 21:39:29 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
IOutboundSessionMaker*
|
2019-06-26 21:39:29 +00:00
|
|
|
LinkManager::GetSessionMaker() const
|
|
|
|
{
|
|
|
|
return _sessionMaker;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::SendTo(
|
|
|
|
const RouterID& remote, const llarp_buffer_t& buf, ILinkSession::CompletionHandler completed)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
auto link = GetLinkWithSessionTo(remote);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (link == nullptr)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (completed)
|
2019-07-26 16:19:31 +00:00
|
|
|
{
|
|
|
|
completed(ILinkSession::DeliveryStatus::eDeliveryDropped);
|
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-07-26 16:19:31 +00:00
|
|
|
return link->SendTo(remote, buf, completed);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::HasSessionTo(const RouterID& remote) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return GetLinkWithSessionTo(remote) != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
LinkManager::PumpLinks()
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
link->Pump();
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
link->Pump();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
LinkManager::AddLink(LinkLayer_ptr link, bool inbound)
|
|
|
|
{
|
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 l(_mutex);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (inbound)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
inboundLinks.emplace(link);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outboundLinks.emplace(link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-06-11 11:44:02 +00:00
|
|
|
LinkManager::StartLinks(Logic_ptr logic)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
LogInfo("starting ", outboundLinks.size(), " outbound links");
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-06-11 11:44:02 +00:00
|
|
|
if (!link->Start(logic))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
LogWarn("outbound link '", link->Name(), "' failed to start");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
LogDebug("Outbound Link ", link->Name(), " started");
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (inboundLinks.size())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
LogInfo("starting ", inboundLinks.size(), " inbound links");
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-06-11 11:44:02 +00:00
|
|
|
if (!link->Start(logic))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
LogWarn("Link ", link->Name(), " failed to start");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
LogDebug("Inbound Link ", link->Name(), " started");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
LinkManager::Stop()
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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 l(_mutex);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
LogInfo("stopping links");
|
|
|
|
stopping = true;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
link->Stop();
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
link->Stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::PersistSessionUntil(const RouterID& remote, llarp_time_t until)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
|
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 l(_mutex);
|
2020-04-07 18:38:56 +00:00
|
|
|
auto& curr = m_PersistingSessions[remote];
|
|
|
|
if (until > curr)
|
2020-03-11 20:55:12 +00:00
|
|
|
curr = until;
|
|
|
|
LogDebug("persist session to ", remote, " until ", curr - time_now_ms());
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
LinkManager::ForEachPeer(
|
2020-04-07 18:38:56 +00:00
|
|
|
std::function<void(const ILinkSession*, bool)> visit, bool randomize) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
link->ForEachSession([visit](const ILinkSession* peer) { visit(peer, true); }, randomize);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
link->ForEachSession([visit](const ILinkSession* peer) { visit(peer, false); }, randomize);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::ForEachPeer(std::function<void(ILinkSession*)> visit)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
link->ForEachSession([visit](ILinkSession* peer) { visit(peer); });
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
link->ForEachSession([visit](ILinkSession* peer) { visit(peer); });
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::ForEachInboundLink(std::function<void(LinkLayer_ptr)> visit) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
visit(link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
LinkManager::NumberOfConnectedRouters() const
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
std::set<RouterID> connectedRouters;
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
auto fn = [&connectedRouters](const ILinkSession* session, bool) {
|
|
|
|
if (session->IsEstablished())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
const RouterContact rc(session->GetRemoteRC());
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rc.IsPublicRouter())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
connectedRouters.insert(rc.pubkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ForEachPeer(fn);
|
|
|
|
|
|
|
|
return connectedRouters.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
LinkManager::NumberOfConnectedClients() const
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
std::set<RouterID> connectedClients;
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
auto fn = [&connectedClients](const ILinkSession* session, bool) {
|
|
|
|
if (session->IsEstablished())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
const RouterContact rc(session->GetRemoteRC());
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!rc.IsPublicRouter())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
connectedClients.insert(rc.pubkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ForEachPeer(fn);
|
|
|
|
|
|
|
|
return connectedClients.size();
|
|
|
|
}
|
|
|
|
|
2019-12-03 17:03:19 +00:00
|
|
|
size_t
|
|
|
|
LinkManager::NumberOfPendingConnections() const
|
|
|
|
{
|
|
|
|
size_t pending = 0;
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-12-03 17:03:19 +00:00
|
|
|
{
|
|
|
|
pending += link->NumberOfPendingSessions();
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-12-03 17:03:19 +00:00
|
|
|
{
|
|
|
|
pending += link->NumberOfPendingSessions();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pending;
|
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
bool
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::GetRandomConnectedRouter(RouterContact& router) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
std::unordered_map<RouterID, RouterContact, RouterID::Hash> connectedRouters;
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
ForEachPeer(
|
2020-04-07 18:38:56 +00:00
|
|
|
[&connectedRouters](const ILinkSession* peer, bool unused) {
|
2019-06-26 21:39:29 +00:00
|
|
|
(void)unused;
|
|
|
|
connectedRouters[peer->GetPubKey()] = peer->GetRemoteRC();
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
|
|
|
|
const auto sz = connectedRouters.size();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (sz)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
auto itr = connectedRouters.begin();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (sz > 1)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
std::advance(itr, randint() % sz);
|
|
|
|
}
|
|
|
|
|
|
|
|
router = itr->second;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
LinkManager::CheckPersistingSessions(llarp_time_t now)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
std::vector<RouterID> sessionsNeeded;
|
2019-06-26 21:39:29 +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 l(_mutex);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
auto itr = m_PersistingSessions.begin();
|
2020-04-07 18:38:56 +00:00
|
|
|
while (itr != m_PersistingSessions.end())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (now < itr->second)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2019-12-05 14:54:44 +00:00
|
|
|
auto link = GetLinkWithSessionTo(itr->first);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (link)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
link->KeepAliveSessionTo(itr->first);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sessionsNeeded.push_back(itr->first);
|
|
|
|
}
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const RouterID r(itr->first);
|
|
|
|
LogInfo("commit to ", r, " expired");
|
|
|
|
itr = m_PersistingSessions.erase(itr);
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-12-05 14:54:44 +00:00
|
|
|
{
|
2019-12-05 15:11:20 +00:00
|
|
|
link->CloseSessionTo(r);
|
2019-12-05 14:54:44 +00:00
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& router : sessionsNeeded)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
_sessionMaker->CreateSessionTo(router, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 16:00:30 +00:00
|
|
|
void
|
|
|
|
LinkManager::updatePeerDb(std::shared_ptr<PeerDb> peerDb)
|
|
|
|
{
|
|
|
|
std::vector<std::pair<RouterID, SessionStats>> statsToUpdate;
|
|
|
|
|
|
|
|
int64_t diffTotalTX = 0;
|
|
|
|
|
|
|
|
ForEachPeer([&](ILinkSession* session) {
|
|
|
|
// derive RouterID
|
|
|
|
RouterID id = RouterID(session->GetRemoteRC().pubkey);
|
|
|
|
|
|
|
|
SessionStats sessionStats = session->GetSessionStats();
|
|
|
|
SessionStats diff;
|
|
|
|
SessionStats& lastStats = m_lastRouterStats[id];
|
|
|
|
|
|
|
|
// TODO: operator overloads / member func for diff
|
|
|
|
diff.currentRateRX = std::max(sessionStats.currentRateRX, lastStats.currentRateRX);
|
|
|
|
diff.currentRateTX = std::max(sessionStats.currentRateTX, lastStats.currentRateTX);
|
|
|
|
diff.totalPacketsRX = sessionStats.totalPacketsRX - lastStats.totalPacketsRX;
|
|
|
|
diff.totalAckedTX = sessionStats.totalAckedTX - lastStats.totalAckedTX;
|
|
|
|
diff.totalDroppedTX = sessionStats.totalDroppedTX - lastStats.totalDroppedTX;
|
|
|
|
|
|
|
|
diffTotalTX = diff.totalAckedTX + diff.totalDroppedTX + diff.totalInFlightTX;
|
|
|
|
|
|
|
|
lastStats = sessionStats;
|
|
|
|
|
|
|
|
// TODO: if we have both inbound and outbound session, this will overwrite
|
|
|
|
statsToUpdate.push_back({id, diff});
|
|
|
|
});
|
|
|
|
|
|
|
|
for (auto& routerStats : statsToUpdate)
|
|
|
|
{
|
|
|
|
peerDb->modifyPeerStats(routerStats.first, [&](PeerStats& stats) {
|
|
|
|
// TODO: store separate stats for up vs down
|
|
|
|
const auto& diff = routerStats.second;
|
|
|
|
|
|
|
|
// note that 'currentRateRX' and 'currentRateTX' are per-second
|
|
|
|
stats.peakBandwidthBytesPerSec = std::max(
|
|
|
|
stats.peakBandwidthBytesPerSec,
|
|
|
|
(double)std::max(diff.currentRateRX, diff.currentRateTX));
|
|
|
|
stats.numPacketsDropped += diff.totalDroppedTX;
|
|
|
|
stats.numPacketsSent = diff.totalAckedTX;
|
|
|
|
stats.numPacketsAttempted = diffTotalTX;
|
|
|
|
|
|
|
|
// TODO: others -- we have slight mismatch on what we store
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
util::StatusObject
|
|
|
|
LinkManager::ExtractStatus() const
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
std::vector<util::StatusObject> ob_links, ib_links;
|
|
|
|
std::transform(
|
|
|
|
inboundLinks.begin(),
|
|
|
|
inboundLinks.end(),
|
|
|
|
std::back_inserter(ib_links),
|
|
|
|
[](const auto& link) -> util::StatusObject { return link->ExtractStatus(); });
|
|
|
|
std::transform(
|
|
|
|
outboundLinks.begin(),
|
|
|
|
outboundLinks.end(),
|
|
|
|
std::back_inserter(ob_links),
|
|
|
|
[](const auto& link) -> util::StatusObject { return link->ExtractStatus(); });
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
util::StatusObject obj{{"outbound", ob_links}, {"inbound", ib_links}};
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::Init(IOutboundSessionMaker* sessionMaker)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
stopping = false;
|
2019-06-26 21:39:29 +00:00
|
|
|
_sessionMaker = sessionMaker;
|
|
|
|
}
|
|
|
|
|
|
|
|
LinkLayer_ptr
|
2020-04-07 18:38:56 +00:00
|
|
|
LinkManager::GetLinkWithSessionTo(const RouterID& remote) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (stopping)
|
2019-06-26 21:39:29 +00:00
|
|
|
return nullptr;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : outboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (link->HasSessionTo(remote))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& link : inboundLinks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (link->HasSessionTo(remote))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace llarp
|