15#include "receive_buffer.h"
16#include "chained_send_buffer.h"
20#ifdef RATS_SEARCH_FEATURES
21#include "bittorrent.h"
30#include <unordered_map>
33#include <unordered_set>
37#include "rats_export.h"
60 std::unique_ptr<rats::NoiseHandshakeState>
noise_hs;
106 RatsPeer(
const std::string&
id,
const std::string& peer_ip, uint16_t peer_port,
107 socket_t sock,
const std::string& norm_addr,
bool outgoing)
193 ReconnectInfo(
const std::string&
id,
const std::string& peer_ip, uint16_t peer_port,
194 std::chrono::milliseconds duration,
bool stable)
236 uint32_t network_magic = htonl(
magic);
237 memcpy(data.data(), &network_magic, 4);
238 data[4] =
static_cast<uint8_t
>(
type);
251 uint32_t network_magic;
252 memcpy(&network_magic, data.data(), 4);
253 header.
magic = ntohl(network_magic);
288 using MessageCallback = std::function<void(
const std::string&,
const nlohmann::json&)>;
305 RatsClient(
int listen_port,
int max_peers = 10,
const std::string& bind_address =
"");
630 std::function<
void(
const std::vector<std::string>&)> callback);
641 std::function<
void(
const std::vector<std::string>&)> callback =
nullptr);
663 const std::map<std::string, std::string>& txt_records = {});
680 void set_mdns_callback(std::function<
void(
const std::string&,
int,
const std::string&)> callback);
786 void off(
const std::string& message_type);
794 void send(
const std::string& message_type,
const nlohmann::json& data,
SendCallback callback =
nullptr);
803 void send(
const std::string& peer_id,
const std::string& message_type,
const nlohmann::json& data,
SendCallback callback =
nullptr);
998 void on_topic_message(
const std::string& topic, std::function<
void(
const std::string&,
const std::string&,
const std::string&)> callback);
1005 void on_topic_json_message(
const std::string& topic, std::function<
void(
const std::string&,
const std::string&,
const nlohmann::json&)> callback);
1012 void on_topic_peer_joined(
const std::string& topic, std::function<
void(
const std::string&,
const std::string&)> callback);
1019 void on_topic_peer_left(
const std::string& topic, std::function<
void(
const std::string&,
const std::string&)> callback);
1202 std::string
send_file(
const std::string& peer_id,
const std::string& file_path,
1203 const std::string& remote_filename =
"");
1212 std::string
send_directory(
const std::string& peer_id,
const std::string& directory_path,
1213 const std::string& remote_name =
"");
1295 const std::string& username,
const std::string& password);
1339 const std::string& server =
"stun.l.google.com",
1340 uint16_t port = 19302,
1341 int timeout_ms = 5000);
1567 bool storage_put(
const std::string& key,
const std::vector<uint8_t>& value);
1693#ifdef RATS_SEARCH_FEATURES
1730 std::shared_ptr<TorrentDownload>
add_torrent(
const std::string& torrent_file,
1731 const std::string& download_path);
1739 std::shared_ptr<TorrentDownload>
add_torrent(
const TorrentInfo& torrent_info,
1740 const std::string& download_path);
1750 const std::string& download_path);
1760 const std::string& download_path);
1801 std::function<
void(
const TorrentInfo&,
bool,
const std::string&)> callback);
1810 std::function<
void(
const TorrentInfo&,
bool,
const std::string&)> callback);
1822 const std::string& peer_ip,
1824 std::function<
void(
const TorrentInfo&,
bool,
const std::string&)> callback);
1835 const std::string& peer_ip,
1837 std::function<
void(
const TorrentInfo&,
bool,
const std::string&)> callback);
1861 const std::string& path,
1862 const std::vector<std::string>& trackers = {},
1863 const std::string& comment =
"",
1864 TorrentCreationProgressCallback progress_callback =
nullptr);
1875 const std::string& path,
1876 const std::vector<std::string>& trackers = {},
1877 const std::string& comment =
"",
1878 TorrentCreationProgressCallback progress_callback =
nullptr);
1890 const std::string& path,
1891 const std::string& output_file,
1892 const std::vector<std::string>& trackers = {},
1893 const std::string& comment =
"",
1894 TorrentCreationProgressCallback progress_callback =
nullptr);
1907 const std::string& path,
1908 const std::vector<std::string>& trackers = {},
1909 const std::string& comment =
"",
1910 TorrentCreationProgressCallback progress_callback =
nullptr);
1987 std::string bind_address_;
1990 std::atomic<bool> running_;
2013 mutable std::mutex config_mutex_;
2014 std::string our_peer_id_;
2015 std::string data_directory_;
2016 static const std::string CONFIG_FILE_NAME;
2017 static const std::string PEERS_FILE_NAME;
2018 static const std::string PEERS_EVER_FILE_NAME;
2021 mutable std::mutex protocol_config_mutex_;
2022 std::string custom_protocol_name_;
2023 std::string custom_protocol_version_;
2026 mutable std::mutex encryption_mutex_;
2027 bool encryption_enabled_;
2028 rats::NoiseKeyPair noise_static_keypair_;
2029 bool noise_keypair_initialized_;
2032 mutable std::mutex local_addresses_mutex_;
2033 std::unordered_set<std::string> local_interface_addresses_;
2038 std::unordered_set<std::string> auto_interface_addresses_;
2041 mutable std::mutex peers_mutex_;
2042 std::unordered_map<std::string, RatsPeer> peers_;
2043 std::unordered_map<socket_t, std::string> socket_to_peer_id_;
2044 std::unordered_map<std::string, std::string> address_to_peer_id_;
2045 std::atomic<int> validated_peer_count_{0};
2048 std::unique_ptr<IOPoller> poller_;
2049 std::mutex io_mutex_;
2050 std::thread io_thread_;
2051 std::thread management_thread_;
2053 ConnectionCallback connection_callback_;
2054 BinaryDataCallback binary_data_callback_;
2055 StringDataCallback string_data_callback_;
2056 JsonDataCallback json_data_callback_;
2057 DisconnectCallback disconnect_callback_;
2063 std::unique_ptr<DhtClient> dht_client_;
2064 std::unique_ptr<DhtClient> dht_client_v6_;
2067 std::unique_ptr<MdnsClient> mdns_client_;
2068 std::function<void(
const std::string&,
int,
const std::string&)> mdns_callback_;
2071 std::unique_ptr<GossipSub> gossipsub_;
2074 std::unique_ptr<FileTransferManager> file_transfer_manager_;
2077 std::unique_ptr<IceManager> ice_manager_;
2080 mutable std::mutex port_mapping_mutex_;
2081 PortMappingConfig port_mapping_config_;
2082 std::unique_ptr<UpnpClient> upnp_client_;
2083 std::unique_ptr<NatPmpClient> natpmp_client_;
2084 PortMapCallback port_mapping_callback_;
2089 std::string mapped_external_ip_;
2090 uint16_t mapped_external_tcp_port_ = 0;
2091 uint16_t mapped_external_udp_port_ = 0;
2094 bool double_nat_warning_logged_ =
false;
2098 void start_port_mapping();
2099 void stop_port_mapping();
2100 void handle_port_mapping_result(
const PortMapResult& result);
2103 uint16_t get_advertised_port()
const;
2111 std::unique_ptr<NetworkMonitor> network_monitor_;
2112 bool network_change_detection_enabled_ =
true;
2113 mutable std::mutex network_monitor_mutex_;
2114 NetworkChangeCallback network_change_callback_;
2117 std::thread network_recovery_thread_;
2118 std::mutex network_recovery_mutex_;
2119 std::condition_variable network_recovery_cv_;
2120 bool network_recovery_pending_ =
false;
2121 bool network_recovery_stop_ =
false;
2123 void start_network_monitor();
2124 void stop_network_monitor();
2125 void network_recovery_loop();
2126 void handle_network_change(
const std::vector<std::string>& current_addresses);
2127 void recover_after_network_change();
2131 std::unique_ptr<StorageManager> storage_manager_;
2134#ifdef RATS_SEARCH_FEATURES
2136 std::unique_ptr<BitTorrentClient> bittorrent_client_;
2139 void initialize_modules();
2140 void destroy_modules();
2144 void management_loop();
2147 void accept_incoming();
2148 bool handle_readable(
socket_t socket);
2149 bool handle_writable(
socket_t socket);
2150 void handle_disconnect(
socket_t socket);
2153 void poller_add(
socket_t fd, uint32_t events);
2154 void poller_modify(
socket_t fd, uint32_t events);
2158 void handle_post_handshake_completion(
socket_t socket,
const RatsPeer& peer_copy);
2159 void process_message(
socket_t socket,
const std::vector<uint8_t>& data,
const std::string& peer_id);
2162 std::unordered_map<std::string, RatsPeer>::iterator find_peer_by_socket_unlocked(
socket_t socket);
2163 std::unordered_map<std::string, RatsPeer>::const_iterator find_peer_by_socket_unlocked(
socket_t socket)
const;
2166 std::string generate_temporary_peer_id(
socket_t socket,
const std::string& connection_info);
2167 void handle_dht_peer_discovery(
const std::vector<Peer>& peers,
const InfoHash& info_hash);
2168 void handle_mdns_service_discovery(
const MdnsService& service,
bool is_new);
2171 std::vector<uint8_t> create_message_with_header(
const std::vector<uint8_t>& payload,
MessageDataType type);
2172 bool parse_message_with_header(
const std::vector<uint8_t>& message,
MessageHeader& header, std::vector<uint8_t>& payload)
const;
2175 void add_peer_unlocked(
const RatsPeer& peer);
2176 void remove_peer_by_id_unlocked(
const std::string& peer_id);
2177 void mark_manual_disconnect(
const std::string& peer_id);
2178 static std::vector<uint8_t> json_to_binary(
const nlohmann::json& data);
2179 bool is_already_connected_to_address(
const std::string& normalized_address)
const;
2180 std::string normalize_peer_address(
const std::string& ip,
int port)
const;
2185 bool enqueue_message(
socket_t socket,
const std::vector<uint8_t>& data);
2187 bool enqueue_message_unlocked(
RatsPeer& peer,
const std::vector<uint8_t>& data);
2190 struct PeerSendTarget {
2192 std::string peer_id;
2193 std::shared_ptr<rats::NoiseCipherState> send_cipher;
2196 bool send_binary_to_peer_unlocked(
socket_t socket,
const std::vector<uint8_t>& data,
2197 MessageDataType message_type,
2198 std::shared_ptr<rats::NoiseCipherState> send_cipher,
2199 const std::string& peer_id_for_logging);
2203 bool handle_noise_frame(RatsPeer& peer);
2205 void start_noise_handshake_async(RatsPeer& peer);
2208 void initialize_local_addresses();
2209 bool is_blocked_address(
const std::string& ip_address)
const;
2210 bool should_ignore_peer(
const std::string& ip,
int port)
const;
2211 bool can_connect_to_peer(
const std::string& ip,
int port)
const;
2212 static bool parse_address_string(
const std::string& address_str, std::string& out_ip,
int& out_port);
2215 int get_peer_count_unlocked()
const;
2218 static constexpr const char* RATS_PROTOCOL_VERSION =
"1.0";
2219 static constexpr int HANDSHAKE_TIMEOUT_SECONDS = 10;
2220 static constexpr int TCP_CONNECT_TIMEOUT_MS = 10000;
2221 static constexpr int IO_POLL_TIMEOUT_MS = 100;
2222 static constexpr size_t MAX_FRAME_SIZE = 100 * 1024 * 1024;
2223 static constexpr int PEER_RECONNECT_DELAY_MS = 100;
2224 static constexpr int HISTORICAL_RECONNECT_DELAY_MS = 500;
2225 static constexpr int MANAGEMENT_LOOP_INTERVAL_SECONDS = 2;
2226 static constexpr int THREAD_CLEANUP_INTERVAL_SECONDS = 30;
2227 static constexpr int INITIAL_DISCOVERY_DELAY_SECONDS = 5;
2228 static constexpr int MAX_PEERS_REQUEST_COUNT = 5;
2229 static constexpr int CONTENT_HASH_HEX_LENGTH = 40;
2230 static constexpr int64_t TIMESTAMP_SKEW_TOLERANCE_MS = 10LL * 60LL * 1000LL;
2232 struct HandshakeMessage {
2233 std::string protocol;
2234 std::string version;
2235 std::string peer_id;
2236 std::string message_type;
2238 bool encryption_enabled;
2239 uint16_t listen_port;
2242 std::string create_handshake_message(
const std::string& message_type,
const std::string& our_peer_id)
const;
2243 bool parse_handshake_message(
const std::vector<uint8_t>& data, HandshakeMessage& out_msg)
const;
2244 bool validate_handshake_message(
const HandshakeMessage& msg)
const;
2245 bool is_handshake_message(
const std::vector<uint8_t>& data)
const;
2246 bool send_handshake_unlocked(RatsPeer& peer,
const std::string& our_peer_id);
2247 bool handle_handshake_message(
socket_t socket,
const std::string& initial_peer_id,
const std::vector<uint8_t>& data);
2248 void check_handshake_timeouts();
2249 void log_handshake_completion_unlocked(
const RatsPeer& peer);
2252 std::atomic<bool> auto_discovery_running_;
2253 std::thread auto_discovery_thread_;
2254 void automatic_discovery_loop();
2255 void announce_rats_peer();
2258 nlohmann::json create_rats_message(
const std::string& type,
const nlohmann::json& payload,
const std::string& sender_peer_id);
2259 void handle_rats_message(
socket_t socket,
const std::string& peer_id,
const nlohmann::json& message);
2262 void handle_peer_exchange_message(
socket_t socket,
const std::string& peer_id,
const nlohmann::json& payload);
2263 void handle_peers_request_message(
socket_t socket,
const std::string& peer_id,
const nlohmann::json& payload);
2264 void handle_peers_response_message(
socket_t socket,
const std::string& peer_id,
const nlohmann::json& payload);
2267 nlohmann::json create_peer_exchange_message(
const RatsPeer& peer);
2268 void broadcast_peer_exchange_message(
const RatsPeer& new_peer);
2269 nlohmann::json create_peers_request_message(
const std::string& sender_peer_id);
2270 nlohmann::json create_peers_response_message(
const std::vector<RatsPeer>& peers,
const std::string& sender_peer_id);
2271 std::vector<RatsPeer> get_random_peers(
int max_count,
const std::string& exclude_peer_id =
"")
const;
2272 void send_peers_request(
socket_t socket,
const std::string& our_peer_id);
2274 int broadcast_rats_message(
const nlohmann::json& message,
const std::string& exclude_peer_id =
"",
bool validated_only =
true);
2277 mutable std::mutex message_handlers_mutex_;
2279 MessageCallback callback;
2282 MessageHandler(MessageCallback cb,
bool once) : callback(cb), is_once(once) {}
2284 std::unordered_map<std::string, std::vector<MessageHandler>> message_handlers_;
2286 void call_message_handlers(
const std::string& message_type,
const std::string& peer_id,
const nlohmann::json& data);
2289 mutable std::mutex reconnect_mutex_;
2290 std::unordered_map<std::string, ReconnectInfo> reconnect_queue_;
2291 ReconnectConfig reconnect_config_;
2292 std::unordered_set<std::string> manual_disconnect_peers_;
2295 void schedule_reconnect(
const RatsPeer& peer);
2296 void process_reconnect_queue();
2297 void remove_from_reconnect_queue(
const std::string& peer_id);
2298 int get_retry_interval_seconds(
int attempt,
bool is_stable)
const;
2301 std::string generate_persistent_peer_id()
const;
2302 nlohmann::json serialize_peer_for_persistence(
const RatsPeer& peer)
const;
2303 bool deserialize_peer_from_persistence(
const nlohmann::json& json, std::string& ip,
int& port, std::string& peer_id)
const;
2304 std::string get_config_file_path()
const;
2305 std::string get_peers_file_path()
const;
2306 std::string get_peers_ever_file_path()
const;
2307 bool save_peers_to_file();
2308 bool append_peer_to_historical_file(
const RatsPeer& peer);
2309 int load_and_reconnect_historical_peers();
2312 void initialize_noise_keypair();
Main GossipSub implementation class.
ICE-lite Manager for NAT traversal.
RatsClient - Core peer-to-peer networking client.
std::function< void(socket_t, const std::string &, const std::vector< uint8_t > &)> BinaryDataCallback
std::vector< ReconnectInfo > get_reconnect_queue() const
Get information about peers pending reconnection.
LogLevel get_log_level() const
Get the current log level.
std::vector< MdnsService > get_mdns_services() const
Get recently discovered mDNS services.
void on_ice_gathering_state_changed(IceGatheringStateCallback callback)
Set callback for ICE gathering state changes.
std::vector< RatsPeer > get_all_peers() const
Get all connected peers.
void set_encryption_enabled(bool enabled)
Set encryption enabled/disabled.
std::vector< uint8_t > create_torrent_data(const std::string &path, const std::vector< std::string > &trackers={}, const std::string &comment="", TorrentCreationProgressCallback progress_callback=nullptr)
Create a torrent from a file or directory and return raw torrent data.
bool subscribe_to_topic(const std::string &topic)
Subscribe to a GossipSub topic.
bool save_historical_peers()
Save current peers to a historical file.
void stop_mdns_discovery()
Stop mDNS discovery.
std::optional< StunMappedAddress > discover_public_address(const std::string &server="stun.l.google.com", uint16_t port=19302, int timeout_ms=5000)
Perform a simple STUN binding request to discover public address This is a convenience method that do...
std::function< void(socket_t, const std::string &, const nlohmann::json &)> JsonDataCallback
std::function< void(bool, const std::string &)> SendCallback
void set_log_level(const std::string &level_str)
Set the minimum log level using string.
bool cancel_file_transfer(const std::string &transfer_id)
Cancel an active or paused transfer.
void set_file_transfer_config(const FileTransferConfig &config)
Replace the file transfer configuration.
bool is_file_transfer_available() const
Check whether the file transfer manager is initialized.
size_t get_spider_pool_size() const
Get the size of the spider node pool.
bool initialize_encryption(bool enable)
Initialize encryption system.
void set_spider_announce_callback(SpiderAnnounceCallback callback)
Set callback for announce_peer requests (spider mode) Called when other peers announce they have a to...
bool is_dht_running() const
Check if DHT is currently running.
std::function< void(socket_t, const std::string &)> DisconnectCallback
void start_automatic_peer_discovery()
Start automatic peer discovery.
std::string get_log_file_path() const
Get the current log file path.
void set_log_rotation_size(size_t max_size_bytes)
Set log file rotation size.
const StorageConfig & get_storage_config() const
Get current storage configuration.
void set_log_rotate_on_startup(bool enabled)
Enable or disable log rotation on application startup When enabled, the existing log file will be rot...
IceGatheringState get_ice_gathering_state() const
Get ICE gathering state.
void set_string_data_callback(StringDataCallback callback)
Set string data callback (called when string data is received)
int broadcast_binary_to_peers(const std::vector< uint8_t > &data, MessageDataType message_type=MessageDataType::BINARY)
Broadcast binary data to all connected peers (primary method)
bool set_noise_static_keypair(const uint8_t private_key[32])
Set a custom static keypair for Noise Protocol If not set, a new keypair is generated automatically.
std::vector< std::shared_ptr< TorrentDownload > > get_all_torrents()
Get all active torrents.
size_t storage_size() const
Get the number of entries in storage.
int broadcast_string_to_peers(const std::string &data)
Broadcast string data to all connected peers.
std::function< void(const std::vector< std::string > &local_addresses)> NetworkChangeCallback
int broadcast_json_to_peers(const nlohmann::json &data)
Broadcast JSON data to all connected peers.
std::function< void(const std::string &info_hash, const std::string &peer_address)> SpiderAnnounceCallback
Spider announce callback type Called when a peer announces they have a torrent (announce_peer request...
bool send_binary_to_peer_id(const std::string &peer_id, const std::vector< uint8_t > &data, MessageDataType message_type=MessageDataType::BINARY)
Send binary data to a peer by peer_id (preferred)
void on_ice_selected_pair(IceSelectedPairCallback callback)
Set callback for ICE selected pair.
std::optional< std::pair< std::string, uint16_t > > get_public_address() const
Get our public IP address (discovered via STUN)
void clear_spider_state()
Clear spider state (pool and visited nodes) Useful for resetting the spider walk.
void set_spider_mode(bool enable)
Enable spider mode on DHT In spider mode:
std::string get_discovery_hash() const
Get the discovery hash for current protocol configuration.
void set_spider_ignore(bool ignore)
Set spider ignore mode - when true, incoming requests are not processed Useful for rate limiting in s...
bool is_storage_available() const
Check if storage is available.
void add_remote_ice_candidates_from_sdp(const std::vector< std::string > &sdp_lines)
Add remote ICE candidates from SDP attribute lines.
void get_torrent_metadata_from_peer(const InfoHash &info_hash, const std::string &peer_ip, uint16_t peer_port, std::function< void(const TorrentInfo &, bool, const std::string &)> callback)
Get torrent metadata directly from a specific peer (fast path - no DHT search needed) This is more ef...
std::string get_bind_address() const
Get the bind address being used.
bool is_log_timestamps_enabled() const
Check if timestamps are enabled in log output.
void clear_ice_servers()
Clear all ICE (STUN/TURN) servers.
void on_ice_candidates_gathered(IceCandidatesCallback callback)
Set callback for ICE candidates gathered.
std::shared_ptr< TorrentDownload > add_torrent_by_hash(const std::string &info_hash_hex, const std::string &download_path)
Add a torrent by info hash hex string (magnet link style - uses DHT to find peers)
void set_reconnect_enabled(bool enabled)
Enable or disable automatic reconnection to disconnected peers.
bool is_encryption_enabled() const
Check if encryption is enabled.
bool publish_to_topic(const std::string &topic, const std::string &message)
Publish a message to a GossipSub topic.
std::vector< RatsPeer > get_validated_peers() const
Get all peers that have completed handshake.
std::function< void(uint32_t current_piece, uint32_t total_pieces)> TorrentCreationProgressCallback
Torrent creation progress callback type Called during piece hashing to report progress.
void add_remote_ice_candidate(const IceCandidate &candidate)
Add a remote ICE candidate (received from peer via signaling)
void close_ice()
Close ICE manager and release resources.
bool send_string_to_peer(socket_t socket, const std::string &data)
Send string data to a specific peer.
std::string get_our_peer_id() const
Get our own peer ID.
void set_ice_config(const IceConfig &config)
Set ICE configuration.
size_t get_active_torrents_count() const
Get the number of active torrents.
bool storage_has(const std::string &key) const
Check if a key exists in storage.
std::optional< std::vector< uint8_t > > storage_get_binary(const std::string &key) const
Get binary data.
bool unsubscribe_from_topic(const std::string &topic)
Unsubscribe from a GossipSub topic.
void off_topic(const std::string &topic)
Remove all event handlers for a GossipSub topic.
void set_log_level(LogLevel level)
Set the minimum log level.
bool save_configuration()
Save configuration to files.
void disable_bittorrent()
Disable BitTorrent functionality.
std::shared_ptr< TorrentDownload > add_torrent(const std::string &torrent_file, const std::string &download_path)
Add a torrent from a file.
void stop_automatic_peer_discovery()
Stop automatic peer discovery.
std::shared_ptr< TorrentDownload > create_and_seed_torrent(const std::string &path, const std::vector< std::string > &trackers={}, const std::string &comment="", TorrentCreationProgressCallback progress_callback=nullptr)
Create a torrent, add it to the BitTorrent client, and start seeding This combines torrent creation w...
bool storage_delete(const std::string &key)
Delete a key from storage.
void on_storage_sync_complete(StorageSyncCompleteCallback callback)
Set storage sync complete callback.
void off(const std::string &message_type)
Remove all handlers for a message type.
bool is_peer_encrypted(const std::string &peer_id) const
Check if a peer connection is encrypted.
void shutdown_all_threads()
Shutdown all background threads.
void disconnect_peer_by_id(const std::string &peer_id)
Disconnect from a peer by peer_id (preferred)
std::vector< std::string > storage_keys_with_prefix(const std::string &prefix) const
Get keys matching a prefix.
void add_turn_server(const std::string &host, uint16_t port, const std::string &username, const std::string &password)
Add a TURN server for relay-based NAT traversal.
void set_topic_message_validator(const std::string &topic, std::function< ValidationResult(const std::string &, const std::string &, const std::string &)> validator)
Set a message validator for a GossipSub topic.
bool storage_put(const std::string &key, const std::string &value)
Store a string value.
std::string send_directory(const std::string &peer_id, const std::string &directory_path, const std::string &remote_name="")
Send a directory tree (recursively) to a peer.
StorageManager & get_storage_manager()
Get the storage manager instance.
bool is_console_logging_enabled() const
Check if console logging is currently enabled.
void set_log_file_path(const std::string &file_path)
Set the log file path.
void send(const std::string &message_type, const nlohmann::json &data, SendCallback callback=nullptr)
Send a message to all peers.
bool find_peers_by_hash(const std::string &content_hash, std::function< void(const std::vector< std::string > &)> callback)
Find peers by content hash using DHT.
void on_file_transfer_progress(TransferProgressCallback callback)
Set the progress callback (fires for both directions).
bool load_configuration()
Load configuration from files.
std::shared_ptr< FileTransferProgress > get_file_transfer_progress(const std::string &transfer_id) const
Get a progress snapshot, or nullptr if the transfer is unknown.
void clear_log_file()
Clear/reset the current log file.
void set_console_logging_enabled(bool enabled)
Enable or disable console logging When disabled, log messages will not be printed to stdout/stderr Fi...
bool storage_request_sync()
Request storage sync from connected peers.
bool connect_to_peer(const std::string &host, int port)
Connect to a peer via direct TCP connection.
bool is_ice_connected() const
Check if ICE is connected.
bool publish_json_to_topic(const std::string &topic, const nlohmann::json &message)
Publish a JSON message to a GossipSub topic.
void clear_historical_peers()
Clear all historical peers.
void stop()
Stop the RatsClient and close all connections.
std::pair< uint64_t, uint64_t > get_bittorrent_stats() const
Get BitTorrent statistics (downloaded and uploaded bytes)
std::optional< std::string > storage_get_string(const std::string &key) const
Get a string value.
bool enable_bittorrent(int listen_port=6881)
Enable BitTorrent functionality.
GossipSub & get_gossipsub()
Get GossipSub instance for publish-subscribe messaging.
void on_topic_message(const std::string &topic, std::function< void(const std::string &, const std::string &, const std::string &)> callback)
Set a message handler for a GossipSub topic using unified event API pattern.
size_t get_spider_visited_count() const
Get the number of visited nodes in spider mode.
bool accept_file_transfer(const std::string &transfer_id, const std::string &local_path)
Accept an incoming transfer.
bool send_binary_to_peer(socket_t socket, const std::vector< uint8_t > &data, MessageDataType message_type=MessageDataType::BINARY)
Send binary data to a specific peer (primary method)
void get_torrent_metadata(const std::string &info_hash_hex, std::function< void(const TorrentInfo &, bool, const std::string &)> callback)
Get torrent metadata without downloading by hex string (requires DHT to be running)
IceConfig get_ice_config() const
Get current ICE configuration.
bool is_spider_mode() const
Check if spider mode is enabled.
std::function< void(socket_t, const std::string &)> ConnectionCallback
void on(const std::string &message_type, MessageCallback callback)
Register a persistent message handler.
void set_storage_config(const StorageConfig &config)
Set storage configuration.
void add_ignored_address(const std::string &ip_address)
Add an IP address to the ignore list (for blocking connections to self)
void set_connection_callback(ConnectionCallback callback)
Set connection callback (called when a new peer connects)
bool is_peer_limit_reached() const
Check if peer limit has been reached.
bool is_port_mapping_enabled() const
Whether automatic port forwarding is currently enabled.
void set_log_retention_count(int count)
Set the number of log files to retain during rotation.
std::vector< std::shared_ptr< FileTransferProgress > > get_active_file_transfers() const
Get progress snapshots for all non-finished transfers.
bool query_mdns_services()
Manually query for mDNS services.
void on_file_transfer_completed(TransferCompletedCallback callback)
Set the completion callback (fires once per transfer).
std::string send_file(const std::string &peer_id, const std::string &file_path, const std::string &remote_filename="")
Send a file to a peer.
std::optional< IceCandidatePair > get_ice_selected_pair() const
Get the selected ICE candidate pair.
void set_mdns_callback(std::function< void(const std::string &, int, const std::string &)> callback)
Set mDNS service discovery callback.
void on_storage_change(StorageChangeCallback callback)
Set storage change callback.
FileTransferManager & get_file_transfer_manager()
Get the file transfer manager instance.
bool start_mdns_discovery(const std::string &service_instance_name="", const std::map< std::string, std::string > &txt_records={})
Start mDNS service discovery and announcement.
bool is_ice_available() const
Check if ICE is available.
bool start_dht_discovery(int dht_port=6881)
Start DHT discovery on specified port.
void set_disconnect_callback(DisconnectCallback callback)
Set disconnect callback (called when a peer disconnects)
std::shared_ptr< TorrentDownload > add_torrent(const TorrentInfo &torrent_info, const std::string &download_path)
Add a torrent from TorrentInfo.
int load_and_reconnect_peers()
Load saved peers and attempt to reconnect.
void spider_walk()
Trigger a single spider walk iteration Sends find_node to a random node from the spider pool Call thi...
nlohmann::json get_storage_statistics() const
Get storage statistics.
IceManager & get_ice_manager()
Get the ICE manager instance.
bool is_reconnect_enabled() const
Check if automatic reconnection is enabled.
void set_protocol_name(const std::string &protocol_name)
Set custom protocol name for handshakes and DHT discovery.
static std::string get_rats_peer_discovery_hash()
Get the well-known RATS peer discovery hash.
void get_torrent_metadata(const InfoHash &info_hash, std::function< void(const TorrentInfo &, bool, const std::string &)> callback)
Get torrent metadata without downloading (requires DHT to be running)
bool is_network_change_detection_enabled() const
bool is_mdns_running() const
Check if mDNS is currently running.
nlohmann::json get_file_transfer_statistics() const
Get aggregate file transfer statistics as JSON.
void set_resume_data_path(const std::string &path)
Set the directory for storing resume data files Resume data allows torrents to resume from where they...
ReconnectConfig get_reconnect_config() const
Get current reconnection configuration.
bool start()
Start the RatsClient and begin listening for connections.
void on_ice_connection_state_changed(IceConnectionStateCallback callback)
Set callback for ICE connection state changes.
std::vector< uint8_t > get_peer_noise_public_key(const std::string &peer_id) const
Get the remote peer's Noise static public key.
void set_logging_enabled(bool enabled)
Enable or disable file logging When enabled, logs will be written to "rats.log" by default.
bool is_logging_enabled() const
Check if file logging is currently enabled.
std::optional< int64_t > storage_get_int(const std::string &key) const
Get a 64-bit integer value.
void set_binary_data_callback(BinaryDataCallback callback)
Set binary data callback (called when binary data is received)
bool storage_put_json(const std::string &key, const nlohmann::json &value)
Store a JSON document.
void on_port_mapping(PortMapCallback callback)
Register a callback fired whenever a port mapping is established, refreshed, removed or fails (invoke...
bool create_torrent_file(const std::string &path, const std::string &output_file, const std::vector< std::string > &trackers={}, const std::string &comment="", TorrentCreationProgressCallback progress_callback=nullptr)
Create a torrent and save it to a file.
void on_topic_peer_joined(const std::string &topic, std::function< void(const std::string &, const std::string &)> callback)
Set a peer joined handler for a GossipSub topic using unified event API pattern.
void stop_dht_discovery()
Stop DHT discovery.
void set_port_mapping_config(const PortMappingConfig &config)
Replace the full port mapping configuration (takes effect on next start).
bool remove_torrent(const InfoHash &info_hash)
Remove a torrent by info hash.
int get_peer_count() const
Get the number of currently connected peers.
bool is_automatic_discovery_running() const
Check if automatic discovery is running.
void add_stun_server(const std::string &host, uint16_t port=STUN_DEFAULT_PORT)
Add a STUN server for NAT traversal.
std::vector< std::string > storage_keys() const
Get all keys in storage.
std::optional< nlohmann::json > storage_get_json(const std::string &key) const
Get a JSON document.
bool is_gossipsub_available() const
Check if GossipSub is available.
size_t get_reconnect_queue_size() const
Get the number of peers pending reconnection.
socket_t get_peer_socket_by_id(const std::string &peer_id) const
Get socket for a peer by peer_id (preferred)
nlohmann::json get_gossipsub_statistics() const
Get GossipSub statistics.
FileTransferConfig get_file_transfer_config() const
Get the current file transfer configuration.
std::vector< uint8_t > get_noise_static_public_key() const
Get our Noise Protocol static public key.
void set_reconnect_config(const ReconnectConfig &config)
Set reconnection configuration.
bool load_historical_peers()
Load historical peers from a file.
RatsClient(int listen_port, int max_peers=10, const std::string &bind_address="")
Constructor.
bool pause_file_transfer(const std::string &transfer_id)
Pause an active transfer (either direction).
int get_max_peers() const
Get maximum number of peers.
bool send_string_to_peer_id(const std::string &peer_id, const std::string &data)
Send string data to a peer by peer_id (preferred)
void set_json_data_callback(JsonDataCallback callback)
Set JSON data callback (called when JSON data is received)
std::chrono::seconds calculate_discovery_interval() const
Calculate discovery interval based on current peer count Uses graduated scaling: more aggressive when...
bool storage_put(const std::string &key, double value)
Store a double-precision floating point value.
int get_listen_port() const
bool send_json_to_peer_id(const std::string &peer_id, const nlohmann::json &data)
Send JSON data to a peer by peer_id (preferred)
std::function< void(socket_t, const std::string &, const std::string &)> StringDataCallback
void end_of_remote_ice_candidates()
Signal end of remote candidates (trickle ICE complete)
std::vector< std::string > get_topic_mesh_peers(const std::string &topic) const
Get mesh peers for a GossipSub topic.
void disconnect_peer(socket_t socket)
Disconnect from a specific peer.
bool is_gossipsub_running() const
Check if GossipSub is running.
bool is_bittorrent_enabled() const
Check if BitTorrent is enabled.
std::optional< std::pair< std::string, uint16_t > > get_mapped_public_address() const
Get the public (external) address discovered by the port mapping backends.
bool is_subscribed_to_topic(const std::string &topic) const
Check if subscribed to a GossipSub topic.
void restart_ice()
Restart ICE (re-gather candidates and restart checks)
std::shared_ptr< TorrentDownload > add_torrent_by_hash(const InfoHash &info_hash, const std::string &download_path)
Add a torrent by info hash (magnet link style - uses DHT to find peers)
bool is_spider_ignoring() const
Check if spider ignore mode is enabled.
bool is_log_rotate_on_startup_enabled() const
Check if log rotation on startup is enabled.
bool reject_file_transfer(const std::string &transfer_id, const std::string &reason="")
Reject an incoming transfer.
void set_max_peers(int max_peers)
Set maximum number of peers.
IceConnectionState get_ice_connection_state() const
Get current ICE connection state.
std::string get_protocol_version() const
Get current protocol version.
bool announce_for_hash(const std::string &content_hash, uint16_t port=0, std::function< void(const std::vector< std::string > &)> callback=nullptr)
Announce our presence for a content hash with optional peer discovery callback If callback is provide...
std::optional< double > storage_get_double(const std::string &key) const
Get a double-precision floating point value.
std::shared_ptr< TorrentDownload > get_torrent(const InfoHash &info_hash)
Get a torrent by info hash.
void set_protocol_version(const std::string &protocol_version)
Set custom protocol version for handshakes.
bool storage_put(const std::string &key, int64_t value)
Store a 64-bit integer value.
std::string get_protocol_name() const
Get current protocol name.
std::vector< std::string > get_topic_peers(const std::string &topic) const
Get peers subscribed to a GossipSub topic.
void start_ice_checks()
Start ICE connectivity checks.
void on_ice_new_candidate(IceNewCandidateCallback callback)
Set callback for new ICE candidate (trickle ICE)
size_t get_dht_routing_table_size() const
Get the size of the DHT routing table.
std::vector< IceCandidate > get_ice_candidates() const
Get our local ICE candidates Call after gathering is complete.
std::string get_peer_id(socket_t socket) const
Get peer_id for a peer by socket (preferred)
void get_torrent_metadata_from_peer(const std::string &info_hash_hex, const std::string &peer_ip, uint16_t peer_port, std::function< void(const TorrentInfo &, bool, const std::string &)> callback)
Get torrent metadata directly from a specific peer by hex string (fast path)
bool is_running() const
Check if the client is currently running.
bool resume_file_transfer(const std::string &transfer_id)
Resume a paused transfer.
void clear_reconnect_queue()
Clear all pending reconnection attempts.
void set_log_timestamps_enabled(bool enabled)
Enable or disable timestamps in log output.
std::vector< std::string > get_subscribed_topics() const
Get list of subscribed GossipSub topics.
bool gather_ice_candidates()
Start gathering ICE candidates This discovers our public address and generates connection candidates.
bool send_json_to_peer(socket_t socket, const nlohmann::json &data)
Send JSON data to a specific peer.
void on_file_transfer_request(TransferOfferCallback callback)
Set the incoming-offer callback.
std::vector< RatsPeer > get_historical_peers() const
Get all historical peers.
std::optional< RatsPeer > get_peer_by_id(const std::string &peer_id) const
Get peer information by peer ID.
void on_topic_peer_left(const std::string &topic, std::function< void(const std::string &, const std::string &)> callback)
Set a peer left handler for a GossipSub topic using unified event API pattern
std::optional< TorrentInfo > create_torrent_from_path(const std::string &path, const std::vector< std::string > &trackers={}, const std::string &comment="", TorrentCreationProgressCallback progress_callback=nullptr)
Create a torrent from a file or directory and return TorrentInfo This is a synchronous operation that...
void add_port_mapping(PortMapProtocol protocol, uint16_t port)
Request an additional port mapping beyond the automatic listen-port mapping (e.g.
std::optional< RatsPeer > get_peer_by_socket(socket_t socket) const
Get peer information by socket.
void send(const std::string &peer_id, const std::string &message_type, const nlohmann::json &data, SendCallback callback=nullptr)
Send a message to a specific peer.
void set_port_mapping_enabled(bool enabled)
Enable or disable automatic port forwarding.
void set_log_colors_enabled(bool enabled)
Enable or disable colored log output.
std::vector< uint8_t > get_peer_handshake_hash(const std::string &peer_id) const
Get the handshake hash for a peer connection (for channel binding)
bool is_ice_gathering_complete() const
Check if ICE candidate gathering is complete.
bool set_data_directory(const std::string &directory_path)
Set directory where data files will be stored.
void once(const std::string &message_type, MessageCallback callback)
Register a one-time message handler.
void set_network_change_detection_enabled(bool enabled)
Enable or disable automatic reaction to host network changes.
bool is_storage_synced() const
Check if storage is synchronized.
nlohmann::json get_connection_statistics() const
Get connection statistics.
PortMappingConfig get_port_mapping_config() const
Get the current port mapping configuration.
void on_network_changed(NetworkChangeCallback callback)
Register a callback fired (debounced) whenever the set of local interface addresses changes.
std::string get_data_directory() const
Get current data directory path.
bool is_log_colors_enabled() const
Check if colored log output is enabled.
void on_topic_json_message(const std::string &topic, std::function< void(const std::string &, const std::string &, const nlohmann::json &)> callback)
Set a JSON message handler for a GossipSub topic using unified event API pattern.
std::function< void(const std::string &, const nlohmann::json &)> MessageCallback
bool storage_put(const std::string &key, const std::vector< uint8_t > &value)
Store binary data.
ThreadManager - Manages background threads with graceful shutdown.
ICE-lite (Interactive Connectivity Establishment) Implementation.
IceGatheringState
ICE gathering state.
std::function< void(IceGatheringState)> IceGatheringStateCallback
Callback when gathering state changes.
std::function< void(const std::string &topic, const std::string &message, const std::string &sender_peer_id)> MessageHandler
MessageDataType
Message data types for librats message headers.
std::function< void(const std::string &transfer_id, bool success, const std::string &error)> TransferCompletedCallback
uint32_t rats_get_library_abi()
const char * rats_get_library_version_string()
std::function< void(const FileTransferProgress &)> TransferProgressCallback
std::function< void(const IceCandidate &)> IceNewCandidateCallback
Callback when a new candidate is discovered (trickle ICE)
std::function< void(const std::vector< IceCandidate > &)> IceCandidatesCallback
Callback when candidates are gathered.
std::function< void(IceConnectionState)> IceConnectionStateCallback
Callback when connection state changes.
std::function< void(const IceCandidatePair &)> IceSelectedPairCallback
Callback when ICE completes with selected pair.
ValidationResult
Message validation result.
std::unique_ptr< RatsClient > create_rats_client(int listen_port)
std::array< uint8_t, NODE_ID_SIZE > InfoHash
void rats_get_library_version(int *major, int *minor, int *patch, int *build)
const char * rats_get_library_git_describe()
std::function< void(const IncomingTransferOffer &)> TransferOfferCallback
IceConnectionState
ICE connection state.
PeerIOContext - Per-peer async I/O buffers and framing state.
std::unique_ptr< rats::NoiseHandshakeState > noise_hs
ChainedSendBuffer send_buffer
ReceiveBuffer recv_buffer
RatsPeer struct - comprehensive information about a connected rats peer.
std::shared_ptr< rats::NoiseCipherState > recv_cipher
std::vector< uint8_t > remote_static_key
RatsPeer(const RatsPeer &o)
bool is_noise_encrypted() const
RatsPeer(RatsPeer &&)=default
std::shared_ptr< rats::NoiseCipherState > send_cipher
bool is_handshake_completed() const
bool noise_handshake_completed
HandshakeState handshake_state
RatsPeer & operator=(const RatsPeer &o)
RatsPeer(const std::string &id, const std::string &peer_ip, uint16_t peer_port, socket_t sock, const std::string &norm_addr, bool outgoing)
RatsPeer & operator=(RatsPeer &&)=default
bool is_handshake_failed() const
std::chrono::steady_clock::time_point handshake_start_time
std::string normalized_address
std::chrono::steady_clock::time_point connected_at
ReconnectConfig - Configuration for automatic peer reconnection.
std::vector< int > retry_intervals_seconds
int stable_first_retry_seconds
int stable_connection_threshold_seconds
ReconnectInfo - Information about a peer pending reconnection.
ReconnectInfo(const std::string &id, const std::string &peer_ip, uint16_t peer_port, std::chrono::milliseconds duration, bool stable)
std::chrono::milliseconds connection_duration
std::chrono::steady_clock::time_point next_attempt_time