2018-12-12 01:32:10 +00:00
|
|
|
#include <link/server.hpp>
|
2019-10-02 13:06:14 +00:00
|
|
|
#include <ev/ev.hpp>
|
2019-01-13 16:30:07 +00:00
|
|
|
#include <crypto/crypto.hpp>
|
2019-12-03 17:58:53 +00:00
|
|
|
#include <config/key_manager.hpp>
|
|
|
|
#include <memory>
|
2019-01-10 19:41:51 +00:00
|
|
|
#include <util/fs.hpp>
|
2019-08-29 11:45:58 +00:00
|
|
|
#include <utility>
|
2019-11-28 20:41:02 +00:00
|
|
|
#include <unordered_set>
|
2019-01-10 19:41:51 +00:00
|
|
|
|
2020-02-24 19:40:45 +00:00
|
|
|
static constexpr auto LINK_LAYER_TICK_INTERVAL = 100ms;
|
2019-11-23 05:05:07 +00:00
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
2019-05-08 12:17:48 +00:00
|
|
|
static constexpr size_t MaxSessionsPerKey = 16;
|
|
|
|
|
2019-12-05 16:12:26 +00:00
|
|
|
ILinkLayer::ILinkLayer(std::shared_ptr< KeyManager > keyManager,
|
|
|
|
GetRCFunc getrc, LinkMessageHandler handler,
|
|
|
|
SignBufferFunc signbuf,
|
2018-12-17 20:46:08 +00:00
|
|
|
SessionEstablishedHandler establishedSession,
|
2018-12-19 16:17:41 +00:00
|
|
|
SessionRenegotiateHandler reneg,
|
2019-11-04 18:53:53 +00:00
|
|
|
TimeoutHandler timeout, SessionClosedHandler closed,
|
|
|
|
PumpDoneHandler pumpDone)
|
2019-08-29 11:45:58 +00:00
|
|
|
: HandleMessage(std::move(handler))
|
|
|
|
, HandleTimeout(std::move(timeout))
|
|
|
|
, Sign(std::move(signbuf))
|
|
|
|
, GetOurRC(std::move(getrc))
|
|
|
|
, SessionEstablished(std::move(establishedSession))
|
|
|
|
, SessionClosed(std::move(closed))
|
|
|
|
, SessionRenegotiate(std::move(reneg))
|
2019-11-04 18:53:53 +00:00
|
|
|
, PumpDone(std::move(pumpDone))
|
2019-12-06 17:31:19 +00:00
|
|
|
, m_RouterEncSecret(keyManager->encryptionKey)
|
|
|
|
, m_SecretKey(keyManager->transportKey)
|
2018-12-17 20:46:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-08-29 11:45:58 +00:00
|
|
|
ILinkLayer::~ILinkLayer() = default;
|
2018-09-03 13:10:56 +00:00
|
|
|
|
|
|
|
bool
|
2019-01-02 01:03:53 +00:00
|
|
|
ILinkLayer::HasSessionTo(const RouterID& id)
|
2018-09-03 13:10:56 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2019-01-02 01:03:53 +00:00
|
|
|
return m_AuthedLinks.find(id) != m_AuthedLinks.end();
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 18:18:12 +00:00
|
|
|
void
|
2019-04-08 12:01:52 +00:00
|
|
|
ILinkLayer::ForEachSession(std::function< void(const ILinkSession*) > visit,
|
|
|
|
bool randomize) const
|
2018-10-25 18:18:12 +00:00
|
|
|
{
|
2019-07-03 12:42:11 +00:00
|
|
|
std::vector< std::shared_ptr< ILinkSession > > sessions;
|
2019-04-03 19:05:44 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2019-07-03 12:42:11 +00:00
|
|
|
if(m_AuthedLinks.size() == 0)
|
|
|
|
return;
|
|
|
|
const size_t sz = randint() % m_AuthedLinks.size();
|
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
auto begin = itr;
|
|
|
|
if(randomize)
|
2019-04-03 19:05:44 +00:00
|
|
|
{
|
2019-07-03 12:42:11 +00:00
|
|
|
std::advance(itr, sz);
|
|
|
|
begin = itr;
|
|
|
|
}
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
|
|
|
sessions.emplace_back(itr->second);
|
2019-04-03 19:05:44 +00:00
|
|
|
++itr;
|
|
|
|
}
|
2019-07-03 12:42:11 +00:00
|
|
|
if(randomize)
|
|
|
|
{
|
|
|
|
itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != begin)
|
|
|
|
{
|
|
|
|
sessions.emplace_back(itr->second);
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2019-04-03 19:05:44 +00:00
|
|
|
}
|
2019-07-03 12:42:11 +00:00
|
|
|
for(const auto& session : sessions)
|
|
|
|
visit(session.get());
|
2018-10-25 18:18:12 +00:00
|
|
|
}
|
|
|
|
|
2018-12-19 16:17:41 +00:00
|
|
|
bool
|
2019-01-02 01:03:53 +00:00
|
|
|
ILinkLayer::VisitSessionByPubkey(const RouterID& pk,
|
2018-12-19 16:17:41 +00:00
|
|
|
std::function< bool(ILinkSession*) > visit)
|
|
|
|
{
|
2019-07-03 12:42:11 +00:00
|
|
|
std::shared_ptr< ILinkSession > session;
|
2018-12-19 16:17:41 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2019-07-03 12:42:11 +00:00
|
|
|
auto itr = m_AuthedLinks.find(pk);
|
|
|
|
if(itr == m_AuthedLinks.end())
|
|
|
|
return false;
|
|
|
|
session = itr->second;
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
2019-07-03 12:42:11 +00:00
|
|
|
return visit(session.get());
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ILinkLayer::ForEachSession(std::function< void(ILinkSession*) > visit)
|
|
|
|
{
|
2019-07-03 12:42:11 +00:00
|
|
|
std::vector< std::shared_ptr< ILinkSession > > sessions;
|
2018-12-19 16:17:41 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2019-07-03 12:42:11 +00:00
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
|
|
|
sessions.emplace_back(itr->second);
|
|
|
|
++itr;
|
|
|
|
}
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
2019-07-03 12:42:11 +00:00
|
|
|
for(const auto& s : sessions)
|
|
|
|
visit(s.get());
|
2018-12-19 16:17:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
bool
|
2019-04-08 12:01:52 +00:00
|
|
|
ILinkLayer::Configure(llarp_ev_loop_ptr loop, const std::string& ifname,
|
|
|
|
int af, uint16_t port)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-05-21 15:24:20 +00:00
|
|
|
m_Loop = loop;
|
2018-09-03 13:10:56 +00:00
|
|
|
m_udp.user = this;
|
2019-10-02 13:06:14 +00:00
|
|
|
m_udp.recvfrom = nullptr;
|
2018-09-03 13:10:56 +00:00
|
|
|
m_udp.tick = &ILinkLayer::udp_tick;
|
|
|
|
if(ifname == "*")
|
|
|
|
{
|
|
|
|
if(!AllInterfaces(af, m_ourAddr))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if(!GetIFAddr(ifname, m_ourAddr, af))
|
2019-07-02 21:28:28 +00:00
|
|
|
m_ourAddr = Addr(ifname);
|
2018-09-04 19:15:06 +00:00
|
|
|
m_ourAddr.port(port);
|
2019-04-08 12:01:52 +00:00
|
|
|
return llarp_ev_add_udp(m_Loop.get(), &m_udp, m_ourAddr) != -1;
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ILinkLayer::Pump()
|
|
|
|
{
|
2019-11-28 20:41:02 +00:00
|
|
|
std::unordered_set< RouterID, RouterID::Hash > closedSessions;
|
2019-11-29 01:02:20 +00:00
|
|
|
std::vector< std::shared_ptr< ILinkSession > > closedPending;
|
2018-12-17 20:46:08 +00:00
|
|
|
auto _now = Now();
|
2018-09-03 13:10:56 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2018-09-07 20:36:06 +00:00
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2019-08-29 11:45:58 +00:00
|
|
|
if(not itr->second->TimedOut(_now))
|
2018-09-07 20:36:06 +00:00
|
|
|
{
|
|
|
|
itr->second->Pump();
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
else
|
2018-11-19 21:55:41 +00:00
|
|
|
{
|
2018-12-11 13:33:23 +00:00
|
|
|
llarp::LogInfo("session to ", RouterID(itr->second->GetPubKey()),
|
|
|
|
" timed out");
|
2019-05-25 14:54:30 +00:00
|
|
|
itr->second->Close();
|
2019-11-28 20:41:02 +00:00
|
|
|
closedSessions.emplace(itr->first);
|
2018-09-07 20:36:06 +00:00
|
|
|
itr = m_AuthedLinks.erase(itr);
|
2018-11-19 21:55:41 +00:00
|
|
|
}
|
2018-09-07 17:41:49 +00:00
|
|
|
}
|
2018-09-07 20:36: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
|
|
|
Lock_t l(m_PendingMutex);
|
2018-09-07 20:36:06 +00:00
|
|
|
|
|
|
|
auto itr = m_Pending.begin();
|
|
|
|
while(itr != m_Pending.end())
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-08-29 11:45:58 +00:00
|
|
|
if(not itr->second->TimedOut(_now))
|
2018-09-07 20:36:06 +00:00
|
|
|
{
|
2019-01-07 12:47:57 +00:00
|
|
|
itr->second->Pump();
|
2018-09-07 20:36:06 +00:00
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
else
|
2019-03-11 13:01:43 +00:00
|
|
|
{
|
|
|
|
LogInfo("pending session at ", itr->first, " timed out");
|
2019-08-29 11:45:58 +00:00
|
|
|
// defer call so we can acquire mutexes later
|
2019-11-29 01:02:20 +00:00
|
|
|
closedPending.emplace_back(std::move(itr->second));
|
2018-09-07 20:36:06 +00:00
|
|
|
itr = m_Pending.erase(itr);
|
2019-03-11 13:01:43 +00:00
|
|
|
}
|
2018-09-06 13:16:24 +00:00
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
2019-11-28 20:41:02 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2019-11-28 20:41:02 +00:00
|
|
|
for(const auto& r : closedSessions)
|
|
|
|
{
|
|
|
|
if(m_AuthedLinks.count(r) == 0)
|
|
|
|
{
|
|
|
|
SessionClosed(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-29 00:52:11 +00:00
|
|
|
for(const auto& pending : closedPending)
|
|
|
|
{
|
2020-01-21 17:31:48 +00:00
|
|
|
if(pending->IsInbound())
|
|
|
|
continue;
|
2019-11-29 01:02:20 +00:00
|
|
|
HandleTimeout(pending.get());
|
2019-11-29 00:52:11 +00:00
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:47:57 +00:00
|
|
|
bool
|
2019-01-02 01:03:53 +00:00
|
|
|
ILinkLayer::MapAddr(const RouterID& pk, ILinkSession* s)
|
2018-09-07 17:41:49 +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
|
|
|
Lock_t l_authed(m_AuthedLinksMutex);
|
|
|
|
Lock_t l_pending(m_PendingMutex);
|
2019-01-10 12:30:21 +00:00
|
|
|
llarp::Addr addr = s->GetRemoteEndpoint();
|
2019-01-13 16:30:07 +00:00
|
|
|
auto itr = m_Pending.find(addr);
|
2019-01-04 12:43:53 +00:00
|
|
|
if(itr != m_Pending.end())
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2019-01-10 12:30:21 +00:00
|
|
|
if(m_AuthedLinks.count(pk) > MaxSessionsPerKey)
|
|
|
|
{
|
2019-08-29 11:45:58 +00:00
|
|
|
LogWarn("too many session for ", pk);
|
2019-04-02 09:03:53 +00:00
|
|
|
s->Close();
|
2019-01-10 12:30:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-04-02 09:03:53 +00:00
|
|
|
m_AuthedLinks.emplace(pk, itr->second);
|
2019-01-04 12:43:53 +00:00
|
|
|
itr = m_Pending.erase(itr);
|
2019-01-10 12:30:21 +00:00
|
|
|
return true;
|
2019-01-07 12:47:57 +00:00
|
|
|
}
|
2019-01-10 12:30:21 +00:00
|
|
|
return false;
|
2018-09-07 17:41:49 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
bool
|
2018-09-04 12:41:25 +00:00
|
|
|
ILinkLayer::PickAddress(const RouterContact& rc,
|
|
|
|
llarp::AddressInfo& picked) const
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
|
|
|
std::string OurDialect = Name();
|
|
|
|
for(const auto& addr : rc.addrs)
|
|
|
|
{
|
|
|
|
if(addr.dialect == OurDialect)
|
|
|
|
{
|
|
|
|
picked = addr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-15 22:19:19 +00:00
|
|
|
util::StatusObject
|
|
|
|
ILinkLayer::ExtractStatus() const
|
|
|
|
{
|
2019-02-18 23:58:12 +00:00
|
|
|
std::vector< util::StatusObject > pending, established;
|
|
|
|
|
2019-03-03 20:51:47 +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
|
|
|
Lock_t l(m_PendingMutex);
|
2019-03-03 20:51:47 +00:00
|
|
|
std::transform(m_Pending.cbegin(), m_Pending.cend(),
|
|
|
|
std::back_inserter(pending),
|
|
|
|
[](const auto& item) -> util::StatusObject {
|
|
|
|
return item.second->ExtractStatus();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
{
|
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 l(m_AuthedLinksMutex);
|
2019-03-03 20:51:47 +00:00
|
|
|
std::transform(m_AuthedLinks.cbegin(), m_AuthedLinks.cend(),
|
|
|
|
std::back_inserter(established),
|
|
|
|
[](const auto& item) -> util::StatusObject {
|
|
|
|
return item.second->ExtractStatus();
|
|
|
|
});
|
|
|
|
}
|
2019-02-18 23:58:12 +00:00
|
|
|
|
|
|
|
return {{"name", Name()},
|
|
|
|
{"rank", uint64_t(Rank())},
|
|
|
|
{"addr", m_ourAddr.ToString()},
|
|
|
|
{"sessions",
|
|
|
|
util::StatusObject{{"pending", pending},
|
|
|
|
{"established", established}}}};
|
2019-02-15 22:19:19 +00:00
|
|
|
}
|
|
|
|
|
2018-11-21 14:56:12 +00:00
|
|
|
bool
|
2018-12-19 17:48:29 +00:00
|
|
|
ILinkLayer::TryEstablishTo(RouterContact rc)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-05-08 12:17:48 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2019-05-08 12:17:48 +00:00
|
|
|
if(m_AuthedLinks.count(rc.pubkey) >= MaxSessionsPerKey)
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-04 12:41:25 +00:00
|
|
|
llarp::AddressInfo to;
|
2018-09-03 13:10:56 +00:00
|
|
|
if(!PickAddress(rc, to))
|
2018-11-21 14:56:12 +00:00
|
|
|
return false;
|
2019-05-14 17:35:01 +00:00
|
|
|
const llarp::Addr addr(to);
|
2019-05-08 12:17:48 +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
|
|
|
Lock_t l(m_PendingMutex);
|
2019-05-08 12:17:48 +00:00
|
|
|
if(m_Pending.count(addr) >= MaxSessionsPerKey)
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-02 09:03:53 +00:00
|
|
|
std::shared_ptr< ILinkSession > s = NewOutboundSession(rc, to);
|
2019-01-07 12:47:57 +00:00
|
|
|
if(PutSession(s))
|
|
|
|
{
|
|
|
|
s->Start();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-09-05 17:39:09 +00:00
|
|
|
ILinkLayer::Start(std::shared_ptr< Logic > l,
|
|
|
|
std::shared_ptr< thread::ThreadPool > worker)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-09-05 17:39:09 +00:00
|
|
|
m_Worker = worker;
|
|
|
|
m_Logic = l;
|
2019-11-23 05:05:07 +00:00
|
|
|
ScheduleTick(LINK_LAYER_TICK_INTERVAL);
|
2018-09-03 13:10:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-15 22:19:19 +00:00
|
|
|
void
|
|
|
|
ILinkLayer::Tick(llarp_time_t now)
|
|
|
|
{
|
|
|
|
{
|
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 l(m_AuthedLinksMutex);
|
2019-03-07 15:17:29 +00:00
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
|
|
|
itr->second->Tick(now);
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2019-03-07 22:58:29 +00:00
|
|
|
|
2019-03-07 15:17: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
|
|
|
Lock_t l(m_PendingMutex);
|
2019-03-07 15:17:29 +00:00
|
|
|
auto itr = m_Pending.begin();
|
|
|
|
while(itr != m_Pending.end())
|
|
|
|
{
|
|
|
|
itr->second->Tick(now);
|
|
|
|
++itr;
|
|
|
|
}
|
2019-02-15 22:19:19 +00:00
|
|
|
}
|
2019-12-05 16:31:58 +00:00
|
|
|
{
|
|
|
|
// decay recently closed list
|
|
|
|
auto itr = m_RecentlyClosed.begin();
|
|
|
|
while(itr != m_RecentlyClosed.end())
|
|
|
|
{
|
|
|
|
if(itr->second >= now)
|
|
|
|
itr = m_RecentlyClosed.erase(itr);
|
|
|
|
else
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2019-02-15 22:19:19 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
void
|
|
|
|
ILinkLayer::Stop()
|
|
|
|
{
|
|
|
|
if(m_Logic && tick_id)
|
2018-12-10 14:14:55 +00:00
|
|
|
m_Logic->remove_call(tick_id);
|
2018-09-24 10:23:11 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2018-09-24 10:23:11 +00:00
|
|
|
auto itr = m_AuthedLinks.begin();
|
|
|
|
while(itr != m_AuthedLinks.end())
|
|
|
|
{
|
2019-04-02 09:03:53 +00:00
|
|
|
itr->second->Close();
|
2018-12-24 16:31:58 +00:00
|
|
|
++itr;
|
2018-09-24 10:23:11 +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
|
|
|
Lock_t l(m_PendingMutex);
|
2018-09-24 10:23:11 +00:00
|
|
|
auto itr = m_Pending.begin();
|
|
|
|
while(itr != m_Pending.end())
|
|
|
|
{
|
2019-04-02 09:03:53 +00:00
|
|
|
itr->second->Close();
|
2018-12-24 16:31:58 +00:00
|
|
|
++itr;
|
2018-09-24 10:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-01-02 01:04:04 +00:00
|
|
|
ILinkLayer::CloseSessionTo(const RouterID& remote)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2020-02-24 19:40:45 +00:00
|
|
|
static constexpr auto CloseGraceWindow = 500ms;
|
|
|
|
const auto now = Now();
|
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 l(m_AuthedLinksMutex);
|
2018-12-10 17:22:59 +00:00
|
|
|
RouterID r = remote;
|
|
|
|
llarp::LogInfo("Closing all to ", r);
|
|
|
|
auto range = m_AuthedLinks.equal_range(r);
|
2018-09-07 20:36:06 +00:00
|
|
|
auto itr = range.first;
|
|
|
|
while(itr != range.second)
|
|
|
|
{
|
2019-04-02 09:03:53 +00:00
|
|
|
itr->second->Close();
|
2019-12-05 16:31:58 +00:00
|
|
|
m_RecentlyClosed.emplace(itr->second->GetRemoteEndpoint(),
|
|
|
|
now + CloseGraceWindow);
|
|
|
|
itr = m_AuthedLinks.erase(itr);
|
2018-09-07 20:36:06 +00:00
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-01-02 01:04:04 +00:00
|
|
|
ILinkLayer::KeepAliveSessionTo(const RouterID& remote)
|
2018-09-03 13:10:56 +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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2018-09-07 20:36:06 +00:00
|
|
|
auto range = m_AuthedLinks.equal_range(remote);
|
|
|
|
auto itr = range.first;
|
|
|
|
while(itr != range.second)
|
|
|
|
{
|
2019-03-18 12:25:32 +00:00
|
|
|
if(itr->second->ShouldPing())
|
|
|
|
itr->second->SendKeepAlive();
|
2018-09-07 20:36:06 +00:00
|
|
|
++itr;
|
|
|
|
}
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-07-26 16:19:31 +00:00
|
|
|
ILinkLayer::SendTo(const RouterID& remote, const llarp_buffer_t& buf,
|
|
|
|
ILinkSession::CompletionHandler completed)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-10-02 13:06:14 +00:00
|
|
|
std::shared_ptr< ILinkSession > s;
|
2018-09-07 20:36: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
|
|
|
Lock_t l(m_AuthedLinksMutex);
|
2018-11-05 13:19:08 +00:00
|
|
|
auto range = m_AuthedLinks.equal_range(remote);
|
|
|
|
auto itr = range.first;
|
|
|
|
// pick lowest backlog session
|
|
|
|
size_t min = std::numeric_limits< size_t >::max();
|
|
|
|
|
|
|
|
while(itr != range.second)
|
2018-09-18 20:56:22 +00:00
|
|
|
{
|
2019-10-02 13:06:14 +00:00
|
|
|
const auto backlog = itr->second->SendQueueBacklog();
|
2018-11-05 13:19:08 +00:00
|
|
|
if(backlog < min)
|
|
|
|
{
|
2019-10-02 13:06:14 +00:00
|
|
|
s = itr->second;
|
2018-11-05 13:19:08 +00:00
|
|
|
min = backlog;
|
|
|
|
}
|
|
|
|
++itr;
|
2018-09-18 20:56:22 +00:00
|
|
|
}
|
2018-09-07 20:36:06 +00:00
|
|
|
}
|
2019-09-12 18:19:25 +00:00
|
|
|
ILinkSession::Message_t pkt(buf.sz);
|
|
|
|
std::copy_n(buf.base, buf.sz, pkt.begin());
|
|
|
|
return s && s->SendMessageBuffer(std::move(pkt), completed);
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ILinkLayer::GetOurAddressInfo(llarp::AddressInfo& addr) const
|
|
|
|
{
|
|
|
|
addr.dialect = Name();
|
|
|
|
addr.pubkey = TransportPubKey();
|
|
|
|
addr.rank = Rank();
|
|
|
|
addr.port = m_ourAddr.port();
|
|
|
|
addr.ip = *m_ourAddr.addr6();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const byte_t*
|
|
|
|
ILinkLayer::TransportPubKey() const
|
|
|
|
{
|
2018-09-04 12:55:20 +00:00
|
|
|
return llarp::seckey_topublic(TransportSecretKey());
|
|
|
|
}
|
|
|
|
|
2019-01-02 01:04:04 +00:00
|
|
|
const SecretKey&
|
2018-09-04 12:55:20 +00:00
|
|
|
ILinkLayer::TransportSecretKey() const
|
|
|
|
{
|
|
|
|
return m_SecretKey;
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 12:47:57 +00:00
|
|
|
bool
|
2019-04-02 09:03:53 +00:00
|
|
|
ILinkLayer::PutSession(const std::shared_ptr< ILinkSession >& s)
|
2018-09-07 17:41:49 +00:00
|
|
|
{
|
2019-03-26 13:51:57 +00:00
|
|
|
static constexpr size_t MaxSessionsPerEndpoint = 5;
|
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(m_PendingMutex);
|
2019-01-09 14:21:55 +00:00
|
|
|
llarp::Addr addr = s->GetRemoteEndpoint();
|
2019-03-26 13:51:57 +00:00
|
|
|
if(m_Pending.count(addr) >= MaxSessionsPerEndpoint)
|
2019-01-07 12:47:57 +00:00
|
|
|
return false;
|
2019-04-02 09:03:53 +00:00
|
|
|
m_Pending.emplace(addr, s);
|
2019-01-07 12:47:57 +00:00
|
|
|
return true;
|
2018-09-07 17:41:49 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
void
|
2019-11-23 05:05:07 +00:00
|
|
|
ILinkLayer::OnTick()
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2018-12-27 19:10:38 +00:00
|
|
|
auto now = Now();
|
|
|
|
Tick(now);
|
2019-11-23 05:05:07 +00:00
|
|
|
ScheduleTick(LINK_LAYER_TICK_INTERVAL);
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-24 19:40:45 +00:00
|
|
|
ILinkLayer::ScheduleTick(llarp_time_t interval)
|
2018-09-03 13:10:56 +00:00
|
|
|
{
|
2019-12-22 14:16:28 +00:00
|
|
|
tick_id =
|
|
|
|
m_Logic->call_later(interval, std::bind(&ILinkLayer::OnTick, this));
|
2018-09-03 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 18:19:25 +00:00
|
|
|
void
|
|
|
|
ILinkLayer::udp_tick(llarp_udp_io* udp)
|
|
|
|
{
|
|
|
|
ILinkLayer* link = static_cast< ILinkLayer* >(udp->user);
|
2019-10-02 13:06:14 +00:00
|
|
|
auto pkts = std::make_shared< llarp_pkt_list >();
|
|
|
|
llarp_ev_udp_recvmany(&link->m_udp, pkts.get());
|
2019-10-16 14:10:11 +00:00
|
|
|
auto logic = link->logic();
|
|
|
|
if(logic == nullptr)
|
|
|
|
return;
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(logic, [pkts, link]() {
|
2019-10-02 13:06:14 +00:00
|
|
|
auto itr = pkts->begin();
|
|
|
|
while(itr != pkts->end())
|
2019-09-12 18:19:25 +00:00
|
|
|
{
|
2019-12-05 16:31:58 +00:00
|
|
|
if(link->m_RecentlyClosed.find(itr->remote)
|
|
|
|
== link->m_RecentlyClosed.end())
|
|
|
|
{
|
|
|
|
link->RecvFrom(itr->remote, std::move(itr->pkt));
|
|
|
|
}
|
2019-09-12 18:19:25 +00:00
|
|
|
++itr;
|
|
|
|
}
|
2019-10-02 13:06:14 +00:00
|
|
|
link->Pump();
|
2019-09-12 18:19:25 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-09-03 13:10:56 +00:00
|
|
|
} // namespace llarp
|