mirror of
https://github.com/lux-tel/libsession-util.git
synced 2026-10-30 20:25:11 +00:00
134 lines
5.3 KiB
C++
134 lines
5.3 KiB
C++
#pragma once
|
|
|
|
#include <filesystem>
|
|
#include <limits>
|
|
#include <optional>
|
|
#include <oxen/quic.hpp>
|
|
|
|
#include "session/network/backends/session_file_server.hpp"
|
|
#include "session/network/network_config.hpp"
|
|
#include "session/network/routing/network_router.hpp"
|
|
#include "session/network/snode_pool.hpp"
|
|
#include "session/network/transport/network_transport.hpp"
|
|
#include "session/platform.hpp"
|
|
#include "session/types.hpp"
|
|
|
|
namespace session::network {
|
|
|
|
namespace detail {
|
|
class RequestQueue;
|
|
}
|
|
|
|
namespace fs = std::filesystem; // NOLINT(misc-unused-alias-decls)
|
|
|
|
class Network : public std::enable_shared_from_this<Network> {
|
|
private:
|
|
const config::Config config;
|
|
std::shared_ptr<oxen::quic::Loop> _loop; // Main loop for network events and syncronization
|
|
std::shared_ptr<oxen::quic::Loop> _disk_loop; // Auxiliary loop for blocking I/O
|
|
std::shared_ptr<SnodePool> _snode_pool;
|
|
std::shared_ptr<ITransport> _transport;
|
|
std::shared_ptr<IRouter> _router;
|
|
bool _suspended = false;
|
|
|
|
std::chrono::steady_clock::time_point _last_successful_clock_resync;
|
|
std::optional<std::string> _current_clock_resync_id;
|
|
std::vector<std::optional<std::chrono::milliseconds>> _clock_resync_results;
|
|
std::shared_ptr<detail::RequestQueue> _clock_resync_request_queue;
|
|
std::shared_ptr<std::vector<std::pair<
|
|
DownloadRequest,
|
|
std::function<void(std::variant<file_metadata, int16_t>, bool)>>>>
|
|
_clock_resync_download_queue;
|
|
|
|
public:
|
|
const config::FileServer file_server_config;
|
|
|
|
// Hook to be notified whenever the network connection status changes.
|
|
std::function<void(ConnectionStatus status)> on_status_changed;
|
|
std::function<void(std::chrono::milliseconds network_time_offset, int hardfork, int softfork)>
|
|
on_network_info_changed;
|
|
|
|
template <typename... Opt>
|
|
requires(!std::is_same_v<
|
|
std::decay_t<std::tuple_element_t<0, std::tuple<Opt...>>>,
|
|
config::Config>)
|
|
Network(Opt&&... opts) : Network(Config(std::forward<Opt>(opts)...)){};
|
|
explicit Network(config::Config config);
|
|
virtual ~Network();
|
|
|
|
bool has_retrieved_time_offset() const {
|
|
return (_last_successful_clock_resync == std::chrono::steady_clock::time_point{});
|
|
};
|
|
std::chrono::milliseconds network_time_offset() const { return _network_time_offset; };
|
|
fork_versions fork() const { return _fork_versions.load(); };
|
|
uint16_t hardfork() const { return _fork_versions.load().hardfork; };
|
|
uint16_t softfork() const { return _fork_versions.load().softfork; };
|
|
|
|
void suspend();
|
|
void resume(bool automatically_reconnect = true);
|
|
void close_connections();
|
|
void clear_cache();
|
|
|
|
ConnectionStatus get_status();
|
|
std::vector<PathInfo> get_active_paths();
|
|
|
|
/// API: network/get_swarm
|
|
///
|
|
/// Retrieves the swarm for the given pubkey. If there is already an entry in the cache for the
|
|
/// swarm then that will be returned, otherwise a network request will be made to retrieve the
|
|
/// swarm and save it to the cache.
|
|
///
|
|
/// Inputs:
|
|
/// - 'swarm_pubkey' - [in] public key for the swarm.
|
|
/// - 'ignore_strike_count' - [in] flag indicating whether node strikes should be ignored when
|
|
/// retrieving the swarm.
|
|
/// - 'callback' - [in] callback to be called with the retrieved swarm (in the case of an error
|
|
/// the callback will be called with an empty list).
|
|
void get_swarm(
|
|
session::network::x25519_pubkey swarm_pubkey,
|
|
bool ignore_strike_count,
|
|
std::function<void(swarm_id_t swarm_id, std::vector<service_node> swarm)> callback);
|
|
|
|
/// API: network/get_random_nodes
|
|
///
|
|
/// Retrieves a number of random nodes from the snode pool. If the are no nodes in the pool a
|
|
/// new pool will be populated and the nodes will be retrieved from that.
|
|
///
|
|
/// Inputs:
|
|
/// - 'count' - [in] the number of nodes to retrieve.
|
|
/// - 'callback' - [in] callback to be called with the retrieved nodes (in the case of an error
|
|
/// the callback will be called with an empty list).
|
|
void get_random_nodes(
|
|
uint16_t count, std::function<void(std::vector<service_node> nodes)> callback);
|
|
|
|
void send_request(Request request, network_response_callback_t callback);
|
|
void upload(UploadRequest request);
|
|
void download(DownloadRequest request);
|
|
|
|
private:
|
|
std::atomic<ConnectionStatus> _status{ConnectionStatus::unknown};
|
|
std::atomic<std::chrono::milliseconds> _network_time_offset{0ms};
|
|
std::atomic<fork_versions> _fork_versions{{0, 0}};
|
|
|
|
void configure();
|
|
|
|
void _close_connections();
|
|
void _recalculate_status();
|
|
void _update_status(ConnectionStatus new_status);
|
|
void _update_network_state(const std::string& body);
|
|
void _handle_421_retry(Request original_request, network_response_callback_t final_callback);
|
|
|
|
void _resync_clock(
|
|
std::optional<Request> original_request, network_response_callback_t request_callback);
|
|
void _launch_next_clock_out_of_sync_request(
|
|
const std::string& request_id,
|
|
const uint8_t index,
|
|
const service_node& node,
|
|
const uint8_t total_requests);
|
|
void _on_clock_resync_complete(const uint8_t total_requests);
|
|
|
|
Request _preprocess_request(Request request);
|
|
};
|
|
|
|
} // namespace session::network
|