2020-01-17 21:54:34 +00:00
|
|
|
#include <chrono>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include "rc_lookup_handler.hpp"
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2023-09-29 21:00:13 +00:00
|
|
|
#include <llarp/link/contacts.hpp>
|
2023-09-13 19:57:18 +00:00
|
|
|
#include <llarp/link/link_manager.hpp>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/crypto/crypto.hpp>
|
|
|
|
#include <llarp/service/context.hpp>
|
|
|
|
#include <llarp/router_contact.hpp>
|
|
|
|
#include <llarp/util/types.hpp>
|
|
|
|
#include <llarp/util/thread/threading.hpp>
|
|
|
|
#include <llarp/nodedb.hpp>
|
2023-09-15 14:55:32 +00:00
|
|
|
#include "router.hpp"
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
#include <iterator>
|
|
|
|
#include <functional>
|
2020-01-16 02:16:18 +00:00
|
|
|
#include <random>
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::add_valid_router(const RouterID& router)
|
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);
|
2023-09-15 14:55:32 +00:00
|
|
|
router_whitelist.insert(router);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::remove_valid_router(const RouterID& router)
|
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);
|
2023-09-15 14:55:32 +00:00
|
|
|
router_whitelist.erase(router);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
2022-10-14 23:55:21 +00:00
|
|
|
static void
|
|
|
|
loadColourList(std::unordered_set<RouterID>& beigelist, const std::vector<RouterID>& new_beige)
|
|
|
|
{
|
|
|
|
beigelist.clear();
|
|
|
|
beigelist.insert(new_beige.begin(), new_beige.end());
|
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::set_router_whitelist(
|
2022-10-14 23:55:21 +00:00
|
|
|
const std::vector<RouterID>& whitelist,
|
|
|
|
const std::vector<RouterID>& greylist,
|
|
|
|
const std::vector<RouterID>& greenlist)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2021-06-07 14:57:33 +00:00
|
|
|
if (whitelist.empty())
|
2019-10-14 15:38:34 +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
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
loadColourList(router_whitelist, whitelist);
|
|
|
|
loadColourList(router_greylist, greylist);
|
|
|
|
loadColourList(router_greenlist, greenlist);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
LogInfo("lokinet service node list now has ", router_whitelist.size(), " active routers");
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
2020-01-16 04:12:38 +00:00
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::has_received_whitelist() const
|
2020-01-16 04:12:38 +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);
|
2023-09-15 14:55:32 +00:00
|
|
|
return not router_whitelist.empty();
|
2020-01-16 04:12:38 +00:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
RouterContact remoteRC;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not forceLookup)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
if (const auto maybe = node_db->Get(router); maybe.has_value())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2021-02-02 14:35:40 +00:00
|
|
|
remoteRC = *maybe;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (callback)
|
2020-01-14 20:12:47 +00:00
|
|
|
{
|
|
|
|
callback(router, &remoteRC, RCRequestResult::Success);
|
|
|
|
}
|
2023-09-15 14:55:32 +00:00
|
|
|
finalize_request(router, &remoteRC, RCRequestResult::Success);
|
2020-01-14 20:12:47 +00:00
|
|
|
return;
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
bool shouldDoLookup = false;
|
|
|
|
|
|
|
|
{
|
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
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
auto itr_pair = pending_callbacks.emplace(router, callback_que{});
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (callback)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
itr_pair.first->second.push_back(callback);
|
|
|
|
}
|
|
|
|
shouldDoLookup = itr_pair.second;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (shouldDoLookup)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
auto fn = [this, router](const auto& res) { handle_dht_lookup_result(router, res); };
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
// if we are a client try using the hidden service endpoints
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!isServiceNode)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
bool sent = false;
|
|
|
|
LogInfo("Lookup ", router, " anonymously");
|
2023-09-15 14:55:32 +00:00
|
|
|
hidden_service_context->ForEachService(
|
2020-04-07 18:38:56 +00:00
|
|
|
[&](const std::string&, const std::shared_ptr<service::Endpoint>& ep) -> bool {
|
2019-06-26 21:39:29 +00:00
|
|
|
const bool success = ep->LookupRouterAnon(router, fn);
|
2020-04-07 18:38:56 +00:00
|
|
|
sent = sent || success;
|
2019-06-26 21:39:29 +00:00
|
|
|
return !success;
|
|
|
|
});
|
2020-04-07 18:38:56 +00:00
|
|
|
if (sent)
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
LogWarn("cannot lookup ", router, " anonymously");
|
|
|
|
}
|
|
|
|
|
2023-09-29 21:00:13 +00:00
|
|
|
if (not contacts->lookup_router(router, fn))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
finalize_request(router, nullptr, RCRequestResult::RouterNotFound);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
2020-01-17 21:54:34 +00:00
|
|
|
else
|
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
router_lookup_times[router] = std::chrono::steady_clock::now();
|
2020-01-17 21:54:34 +00:00
|
|
|
}
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::is_grey_listed(const RouterID& remote) const
|
2021-06-07 14:57:33 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0
|
|
|
|
&& !is_remote_in_bootstrap(remote))
|
2021-06-07 14:57:33 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not useWhitelist)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
util::Lock lock{_mutex};
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
return router_greylist.count(remote);
|
2021-06-07 14:57:33 +00:00
|
|
|
}
|
|
|
|
|
2022-10-14 23:55:21 +00:00
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::is_green_listed(const RouterID& remote) const
|
2022-10-14 23:55:21 +00:00
|
|
|
{
|
|
|
|
util::Lock lock{_mutex};
|
2023-09-15 14:55:32 +00:00
|
|
|
return router_greenlist.count(remote);
|
2022-10-14 23:55:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::is_registered(const RouterID& remote) const
|
2022-10-14 23:55:21 +00:00
|
|
|
{
|
|
|
|
util::Lock lock{_mutex};
|
2023-09-15 14:55:32 +00:00
|
|
|
return router_whitelist.count(remote) || router_greylist.count(remote)
|
|
|
|
|| router_greenlist.count(remote);
|
2022-10-14 23:55:21 +00:00
|
|
|
}
|
|
|
|
|
2021-06-07 14:57:33 +00:00
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::is_path_allowed(const RouterID& remote) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0
|
|
|
|
&& !is_remote_in_bootstrap(remote))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-05-11 13:10:16 +00:00
|
|
|
if (not useWhitelist)
|
|
|
|
return true;
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2021-05-11 13:10:16 +00:00
|
|
|
util::Lock lock{_mutex};
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
return router_whitelist.count(remote);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
2021-06-07 14:57:33 +00:00
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::is_session_allowed(const RouterID& remote) const
|
2021-06-07 14:57:33 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0
|
|
|
|
&& !is_remote_in_bootstrap(remote))
|
2021-06-07 14:57:33 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not useWhitelist)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
util::Lock lock{_mutex};
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
return router_whitelist.count(remote) or router_greylist.count(remote);
|
2021-06-07 14:57:33 +00:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::check_rc(const RouterContact& rc) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
if (not is_session_allowed(rc.pubkey))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-29 21:00:13 +00:00
|
|
|
contacts->delete_rc_node_async(dht::Key_t{rc.pubkey});
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-09-29 21:00:13 +00:00
|
|
|
if (not rc.Verify(llarp::time_now_ms()))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2019-08-28 11:02:00 +00:00
|
|
|
LogWarn("RC for ", RouterID(rc.pubkey), " is invalid");
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update nodedb if required
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rc.IsPublicRouter())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht.");
|
2023-09-15 14:55:32 +00:00
|
|
|
loop->call([rc, n = node_db] { n->PutIfNewer(rc); });
|
2023-09-29 21:00:13 +00:00
|
|
|
contacts->put_rc_node_async(rc);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-09-03 15:56:56 +00:00
|
|
|
size_t
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::num_strict_connect_routers() const
|
2019-09-03 15:56:56 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
return strict_connect_pubkeys.size();
|
2019-09-03 15:56:56 +00:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::get_random_whitelist_router(RouterID& router) const
|
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
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
const auto sz = router_whitelist.size();
|
|
|
|
auto itr = router_whitelist.begin();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (sz == 0)
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
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;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::check_renegotiate_valid(RouterContact newrc, RouterContact oldrc)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-05-14 01:35:15 +00:00
|
|
|
// mismatch of identity ?
|
2020-04-07 18:38:56 +00:00
|
|
|
if (newrc.pubkey != oldrc.pubkey)
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
if (!is_session_allowed(newrc.pubkey))
|
2019-06-26 21:39:29 +00:00
|
|
|
return false;
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
auto func = [this, newrc] { check_rc(newrc); };
|
|
|
|
work_func(func);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
|
|
|
// update dht if required
|
2023-09-29 21:00:13 +00:00
|
|
|
if (contacts->rc_nodes()->HasNode(dht::Key_t{newrc.pubkey}))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-29 21:00:13 +00:00
|
|
|
contacts->rc_nodes()->PutNode(newrc);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: check for other places that need updating the RC
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::periodic_update(llarp_time_t now)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
// try looking up stale routers
|
2021-02-02 14:35:40 +00:00
|
|
|
std::unordered_set<RouterID> routersToLookUp;
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
node_db->VisitInsertedBefore(
|
2020-04-07 18:38:56 +00:00
|
|
|
[&](const RouterContact& rc) {
|
2023-09-15 14:55:32 +00:00
|
|
|
if (has_pending_lookup(rc.pubkey))
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
routersToLookUp.insert(rc.pubkey);
|
|
|
|
},
|
|
|
|
now - RouterContact::UpdateInterval);
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& router : routersToLookUp)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
get_rc(router, nullptr, true);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
node_db->RemoveStaleRCs(boostrap_rid_list, now - RouterContact::StaleInsertionAge);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::explore_network()
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
const size_t known = node_db->NumLoaded();
|
|
|
|
if (bootstrap_rc_list.empty() && known == 0)
|
2020-01-23 17:49:33 +00:00
|
|
|
{
|
|
|
|
LogError("we have no bootstrap nodes specified");
|
|
|
|
}
|
2023-09-15 14:55:32 +00:00
|
|
|
else if (known <= bootstrap_rc_list.size())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
for (const auto& rc : bootstrap_rc_list)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
LogInfo("Doing explore via bootstrap node: ", RouterID(rc.pubkey));
|
2023-09-29 21:00:13 +00:00
|
|
|
// TODO: replace this concept
|
|
|
|
// dht->ExploreNetworkVia(dht::Key_t{rc.pubkey});
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (useWhitelist)
|
2020-01-14 20:12:47 +00:00
|
|
|
{
|
2020-01-17 21:54:34 +00:00
|
|
|
static constexpr auto RerequestInterval = 10min;
|
2020-04-07 18:38:56 +00:00
|
|
|
static constexpr size_t LookupPerTick = 5;
|
2020-01-16 02:16:18 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
std::vector<RouterID> lookupRouters;
|
2020-01-16 02:16:18 +00:00
|
|
|
lookupRouters.reserve(LookupPerTick);
|
|
|
|
|
2020-01-17 21:54:34 +00:00
|
|
|
const auto now = std::chrono::steady_clock::now();
|
|
|
|
|
2020-01-14 20:12:47 +00:00
|
|
|
{
|
|
|
|
// if we are using a whitelist look up a few routers we don't have
|
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);
|
2023-09-15 14:55:32 +00:00
|
|
|
for (const auto& r : router_whitelist)
|
2020-01-14 20:12:47 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
if (now > router_lookup_times[r] + RerequestInterval and not node_db->Has(r))
|
2020-01-17 21:54:34 +00:00
|
|
|
{
|
|
|
|
lookupRouters.emplace_back(r);
|
|
|
|
}
|
2020-01-14 20:12:47 +00:00
|
|
|
}
|
|
|
|
}
|
2020-01-16 02:16:18 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (lookupRouters.size() > LookupPerTick)
|
2020-01-16 02:16:18 +00:00
|
|
|
{
|
2021-03-18 21:36:53 +00:00
|
|
|
std::shuffle(lookupRouters.begin(), lookupRouters.end(), CSRNG{});
|
2020-01-16 02:16:18 +00:00
|
|
|
lookupRouters.resize(LookupPerTick);
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& r : lookupRouters)
|
2023-09-15 14:55:32 +00:00
|
|
|
get_rc(r, nullptr, true);
|
2020-01-14 20:12:47 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-01-30 22:10:56 +00:00
|
|
|
// service nodes gossip, not explore
|
2023-09-29 21:00:13 +00:00
|
|
|
if (contacts->router()->IsServiceNode())
|
2020-01-30 22:10:56 +00:00
|
|
|
return;
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
// explore via every connected peer
|
2023-08-28 20:50:06 +00:00
|
|
|
/*
|
|
|
|
* TODO: DHT explore via libquic
|
|
|
|
*
|
2020-04-07 18:38:56 +00:00
|
|
|
_linkManager->ForEachPeer([&](ILinkSession* s) {
|
|
|
|
if (!s->IsEstablished())
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
const RouterContact rc = s->GetRemoteRC();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rc.IsPublicRouter() && (_bootstrapRCList.find(rc) == _bootstrapRCList.end()))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-02-06 18:57:39 +00:00
|
|
|
LogDebug("Doing explore via public node: ", RouterID(rc.pubkey));
|
2019-06-26 21:39:29 +00:00
|
|
|
_dht->impl->ExploreNetworkVia(dht::Key_t{rc.pubkey});
|
|
|
|
}
|
|
|
|
});
|
2023-08-28 20:50:06 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::init(
|
2023-09-29 21:00:13 +00:00
|
|
|
std::shared_ptr<Contacts> c,
|
2021-02-02 14:35:40 +00:00
|
|
|
std::shared_ptr<NodeDB> nodedb,
|
2023-09-15 14:55:32 +00:00
|
|
|
EventLoop_ptr l,
|
|
|
|
worker_func dowork,
|
2023-09-13 19:57:18 +00:00
|
|
|
LinkManager* linkManager,
|
2020-04-07 18:38:56 +00:00
|
|
|
service::Context* hiddenServiceContext,
|
2021-02-02 14:35:40 +00:00
|
|
|
const std::unordered_set<RouterID>& strictConnectPubkeys,
|
2020-04-07 18:38:56 +00:00
|
|
|
const std::set<RouterContact>& bootstrapRCList,
|
|
|
|
bool useWhitelist_arg,
|
|
|
|
bool isServiceNode_arg)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-29 21:00:13 +00:00
|
|
|
contacts = c;
|
2023-09-15 14:55:32 +00:00
|
|
|
node_db = std::move(nodedb);
|
|
|
|
loop = std::move(l);
|
|
|
|
work_func = std::move(dowork);
|
|
|
|
hidden_service_context = hiddenServiceContext;
|
|
|
|
strict_connect_pubkeys = strictConnectPubkeys;
|
|
|
|
bootstrap_rc_list = bootstrapRCList;
|
|
|
|
link_manager = linkManager;
|
2020-04-07 18:38:56 +00:00
|
|
|
useWhitelist = useWhitelist_arg;
|
|
|
|
isServiceNode = isServiceNode_arg;
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
for (const auto& rc : bootstrap_rc_list)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
boostrap_rid_list.insert(rc.pubkey);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::handle_dht_lookup_result(
|
|
|
|
RouterID remote, const std::vector<RouterContact>& results)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not results.size())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
finalize_request(remote, nullptr, RCRequestResult::RouterNotFound);
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
if (not is_session_allowed(remote))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
finalize_request(remote, &results[0], RCRequestResult::InvalidRouter);
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
if (not check_rc(results[0]))
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
finalize_request(remote, &results[0], RCRequestResult::BadRC);
|
2019-06-26 21:39:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
finalize_request(remote, &results[0], RCRequestResult::Success);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::has_pending_lookup(RouterID remote) const
|
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);
|
2023-09-15 14:55:32 +00:00
|
|
|
return pending_callbacks.find(remote) != pending_callbacks.end();
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::is_remote_in_bootstrap(const RouterID& remote) const
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
for (const auto& rc : bootstrap_rc_list)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (rc.pubkey == remote)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-09-15 14:55:32 +00:00
|
|
|
RCLookupHandler::finalize_request(
|
2020-04-07 18:38:56 +00:00
|
|
|
const RouterID& router, const RouterContact* const rc, RCRequestResult result)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
2023-09-15 14:55:32 +00:00
|
|
|
callback_que movedCallbacks;
|
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
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
auto itr = pending_callbacks.find(router);
|
2019-06-26 21:39:29 +00:00
|
|
|
|
2023-09-15 14:55:32 +00:00
|
|
|
if (itr != pending_callbacks.end())
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
movedCallbacks.splice(movedCallbacks.begin(), itr->second);
|
2023-09-15 14:55:32 +00:00
|
|
|
pending_callbacks.erase(itr);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
} // lock
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& callback : movedCallbacks)
|
2019-06-26 21:39:29 +00:00
|
|
|
{
|
|
|
|
callback(router, rc, result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace llarp
|