Back to Site
Loading...
Searching...
No Matches
librats.h
Go to the documentation of this file.
1#pragma once
2
3#include "socket.h"
4#include "dht.h"
5#include "mdns.h"
6#include "logger.h"
7#include "threadmanager.h"
8#include "gossipsub.h" // For ValidationResult enum and GossipSub types
9#include "file_transfer.h" // File transfer functionality
10#include "noise.h" // Noise Protocol encryption
11#include "ice.h" // ICE-lite NAT traversal
12#include "upnp.h" // UPnP IGD automatic port forwarding
13#include "natpmp.h" // NAT-PMP automatic port forwarding
14#include "io_poller.h" // Platform-optimal I/O multiplexing
15#include "receive_buffer.h" // Efficient receive buffer for async I/O
16#include "chained_send_buffer.h" // Zero-copy chained send buffer
17#ifdef RATS_STORAGE
18#include "storage.h" // Distributed storage functionality
19#endif
20#ifdef RATS_SEARCH_FEATURES
21#include "bittorrent.h" // BitTorrent functionality (optional, requires RATS_SEARCH_FEATURES)
22#endif
23#include "json.hpp" // nlohmann::json
24#include <string>
25#include <functional>
26#include <thread>
27#include <vector>
28#include <mutex>
29#include <atomic>
30#include <unordered_map>
31#include <memory>
32#include <chrono>
33#include <unordered_set>
34#include <cstdint>
35#include <cstring>
36#include <optional>
37#include "rats_export.h"
38
39namespace librats {
40
41// Detects host network configuration changes (defined in network_monitor.h).
42// Forward-declared here; only used via unique_ptr, so RatsClient's destructor
43// (defined in librats.cpp, which includes network_monitor.h) sees the full type.
44class NetworkMonitor;
45
56 ReceiveBuffer recv_buffer{8192};
57 ChainedSendBuffer send_buffer;
58
59 // Async Noise handshake (only valid while handshake_state == NOISE_PENDING)
60 std::unique_ptr<rats::NoiseHandshakeState> noise_hs;
61 int noise_step = 0; // XX pattern: 0→initial, advances per message
62};
63
67struct RatsPeer {
68 std::string peer_id; // Unique hash ID for the peer
69 std::string ip; // IP address
70 uint16_t port; // Port number
71 socket_t socket; // Socket handle
72 std::string normalized_address; // Normalized address for duplicate detection (ip:port)
73 std::chrono::steady_clock::time_point connected_at; // Connection timestamp
74 bool is_outgoing; // True if we initiated the connection, false if incoming
75
76 // Handshake-related fields
77 enum class HandshakeState {
78 PENDING, // Handshake not started
79 SENT, // Handshake sent, waiting for response
80 NOISE_PENDING, // Rats handshake done, Noise handshake in progress
81 COMPLETED, // Handshake completed successfully (including Noise if enabled)
82 FAILED // Handshake failed
83 };
84
85 HandshakeState handshake_state; // Current handshake state
86 std::string version; // Protocol version of remote peer
87 std::chrono::steady_clock::time_point handshake_start_time; // When handshake started
88
89 // Encryption-related fields
90 bool encryption_enabled; // Whether encryption is enabled for this peer
91 bool noise_handshake_completed; // Whether noise handshake is completed
92 std::shared_ptr<rats::NoiseCipherState> send_cipher; // Cipher for sending encrypted data
93 std::shared_ptr<rats::NoiseCipherState> recv_cipher; // Cipher for receiving encrypted data
94 std::vector<uint8_t> remote_static_key; // Remote peer's static public key (for identity verification)
95
96 // Async I/O context (per-peer buffers for non-blocking I/O)
98
100 encryption_enabled(false),
102 connected_at = std::chrono::steady_clock::now();
104 }
105
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)
108 : peer_id(id), ip(peer_ip), port(peer_port), socket(sock),
109 normalized_address(norm_addr), is_outgoing(outgoing),
111 encryption_enabled(false),
113 connected_at = std::chrono::steady_clock::now();
115 }
116
117 // Custom copy: copies all fields except io_ (non-copyable due to unique_ptr).
118 // Copies are used for snapshots passed to callbacks – they never need the IO context.
129
131 if (this != &o) {
132 peer_id = o.peer_id;
133 ip = o.ip;
134 port = o.port;
135 socket = o.socket;
140 version = o.version;
147 // io_ left unchanged in the destination (no copy)
148 }
149 return *this;
150 }
151
152 // Default move operations are fine
153 RatsPeer(RatsPeer&&) = default;
155
156 // Check if peer has completed Noise handshake and is ready for encrypted communication
160
161 // Helper methods
164};
165
170 int max_attempts = 3; // Maximum number of reconnection attempts
171 std::vector<int> retry_intervals_seconds = {5, 30, 120}; // Intervals between attempts (5s, 30s, 2min)
172 int stable_connection_threshold_seconds = 60; // Connection duration to be considered "stable" (1 minute)
173 int stable_first_retry_seconds = 2; // First retry interval for stable peers (faster)
174 bool enabled = true; // Whether auto-reconnection is enabled
175};
176
181 std::string peer_id; // Peer ID for identification
182 std::string ip; // IP address to reconnect to
183 uint16_t port; // Port number
184 int attempt_count; // Current number of reconnection attempts
185 std::chrono::steady_clock::time_point next_attempt_time; // When to attempt next reconnection
186 std::chrono::milliseconds connection_duration; // How long the peer was connected before disconnect
187 bool is_stable; // Whether this was a "stable" connection
188
190 next_attempt_time = std::chrono::steady_clock::now();
191 }
192
193 ReconnectInfo(const std::string& id, const std::string& peer_ip, uint16_t peer_port,
194 std::chrono::milliseconds duration, bool stable)
195 : peer_id(id), ip(peer_ip), port(peer_port), attempt_count(0),
196 connection_duration(duration), is_stable(stable) {
197 next_attempt_time = std::chrono::steady_clock::now();
198 }
199};
200
204enum class MessageDataType : uint8_t {
205 BINARY = 0x01, // Raw binary data
206 STRING = 0x02, // UTF-8 string data
207 JSON = 0x03 // JSON formatted data
208};
209
218 static constexpr uint32_t MAGIC_NUMBER = 0x52415453; // "RATS" in ASCII
219 static constexpr size_t HEADER_SIZE = 8;
220
221 uint32_t magic; // Magic number for validation
222 MessageDataType type; // Message data type
223 uint8_t reserved[3]; // Reserved bytes for future use
224
226 reserved[0] = reserved[1] = reserved[2] = 0;
227 }
228
232
233 // Serialize header to bytes
234 std::vector<uint8_t> serialize() const {
235 std::vector<uint8_t> data(HEADER_SIZE);
236 uint32_t network_magic = htonl(magic);
237 memcpy(data.data(), &network_magic, 4);
238 data[4] = static_cast<uint8_t>(type);
239 data[5] = reserved[0];
240 data[6] = reserved[1];
241 data[7] = reserved[2];
242 return data;
243 }
244
245 // Deserialize header from bytes
246 static bool deserialize(const std::vector<uint8_t>& data, MessageHeader& header) {
247 if (data.size() < HEADER_SIZE) {
248 return false;
249 }
250
251 uint32_t network_magic;
252 memcpy(&network_magic, data.data(), 4);
253 header.magic = ntohl(network_magic);
254
255 if (header.magic != MAGIC_NUMBER) {
256 return false;
257 }
258
259 header.type = static_cast<MessageDataType>(data[4]);
260 header.reserved[0] = data[5];
261 header.reserved[1] = data[6];
262 header.reserved[2] = data[7];
263
264 return true;
265 }
266
267 // Validate data type
268 bool is_valid_type() const {
269 return type == MessageDataType::BINARY ||
272 }
273};
274
278class RATS_API RatsClient : public ThreadManager {
279public:
280 // =========================================================================
281 // Type Definitions and Callbacks
282 // =========================================================================
283 using ConnectionCallback = std::function<void(socket_t, const std::string&)>;
284 using BinaryDataCallback = std::function<void(socket_t, const std::string&, const std::vector<uint8_t>&)>;
285 using StringDataCallback = std::function<void(socket_t, const std::string&, const std::string&)>;
286 using JsonDataCallback = std::function<void(socket_t, const std::string&, const nlohmann::json&)>;
287 using DisconnectCallback = std::function<void(socket_t, const std::string&)>;
288 using MessageCallback = std::function<void(const std::string&, const nlohmann::json&)>;
289 using SendCallback = std::function<void(bool, const std::string&)>;
290 // Fired when the host's network configuration changes (interface up/down, IP
291 // added/removed, default route change). The argument is the new full list of
292 // local interface addresses. See on_network_changed().
293 using NetworkChangeCallback = std::function<void(const std::vector<std::string>& local_addresses)>;
294
295 // =========================================================================
296 // Constructor and Destructor
297 // =========================================================================
298
305 RatsClient(int listen_port, int max_peers = 10, const std::string& bind_address = "");
306
311
312 // =========================================================================
313 // Core Lifecycle Management
314 // =========================================================================
315
320 bool start();
321
325 void stop();
326
331
336 bool is_running() const;
337
338 // =========================================================================
339 // Utility Methods
340 // =========================================================================
341
342 int get_listen_port() const;
343
348 std::string get_bind_address() const;
349
350 // =========================================================================
351 // Connection Management
352 // =========================================================================
353
360 bool connect_to_peer(const std::string& host, int port);
361
367
372 void disconnect_peer_by_id(const std::string& peer_id);
373
374 // =========================================================================
375 // Data Transmission Methods
376 // =========================================================================
377
378 // Send to specific peer by socket
386 bool send_binary_to_peer(socket_t socket, const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
387
394 bool send_string_to_peer(socket_t socket, const std::string& data);
395
402 bool send_json_to_peer(socket_t socket, const nlohmann::json& data);
403
404 // Send to specific peer by ID
412 bool send_binary_to_peer_id(const std::string& peer_id, const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
413
420 bool send_string_to_peer_id(const std::string& peer_id, const std::string& data);
421
428 bool send_json_to_peer_id(const std::string& peer_id, const nlohmann::json& data);
429
430 // Broadcast to all peers
437 int broadcast_binary_to_peers(const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
438
444 int broadcast_string_to_peers(const std::string& data);
445
451 int broadcast_json_to_peers(const nlohmann::json& data);
452
453 // =========================================================================
454 // Peer Information and Management
455 // =========================================================================
456
461 int get_peer_count() const;
462
468 std::string get_peer_id(socket_t socket) const;
469
475 socket_t get_peer_socket_by_id(const std::string& peer_id) const;
476
481 std::string get_our_peer_id() const;
482
487 std::vector<RatsPeer> get_all_peers() const;
488
493 std::vector<RatsPeer> get_validated_peers() const;
494
500 std::optional<RatsPeer> get_peer_by_id(const std::string& peer_id) const;
501
507 std::optional<RatsPeer> get_peer_by_socket(socket_t socket) const;
508
513 int get_max_peers() const;
514
519 void set_max_peers(int max_peers);
520
526
527 // =========================================================================
528 // Automatic Reconnection
529 // =========================================================================
530
535 void set_reconnect_enabled(bool enabled);
536
542
548
554
560
565
570 std::vector<ReconnectInfo> get_reconnect_queue() const;
571
572 // =========================================================================
573 // Callback Registration
574 // =========================================================================
575
581
587
593
599
605
606 // =========================================================================
607 // Peer Discovery Methods
608 // =========================================================================
609
610 // DHT Discovery
616 bool start_dht_discovery(int dht_port = 6881);
617
622
629 bool find_peers_by_hash(const std::string& content_hash,
630 std::function<void(const std::vector<std::string>&)> callback);
631
640 bool announce_for_hash(const std::string& content_hash, uint16_t port = 0,
641 std::function<void(const std::vector<std::string>&)> callback = nullptr);
642
647 bool is_dht_running() const;
648
654
655 // mDNS Discovery
662 bool start_mdns_discovery(const std::string& service_instance_name = "",
663 const std::map<std::string, std::string>& txt_records = {});
664
669
674 bool is_mdns_running() const;
675
680 void set_mdns_callback(std::function<void(const std::string&, int, const std::string&)> callback);
681
686 std::vector<MdnsService> get_mdns_services() const;
687
693
694 // Automatic Discovery
699
704
710
716 std::chrono::seconds calculate_discovery_interval() const;
717
722 std::string get_discovery_hash() const;
723
728 static std::string get_rats_peer_discovery_hash();
729
734 void add_ignored_address(const std::string& ip_address);
735
736 // =========================================================================
737 // Protocol Configuration
738 // =========================================================================
739
744 void set_protocol_name(const std::string& protocol_name);
745
750 void set_protocol_version(const std::string& protocol_version);
751
756 std::string get_protocol_name() const;
757
762 std::string get_protocol_version() const;
763
764 // =========================================================================
765 // Message Exchange API
766 // =========================================================================
767
773 void on(const std::string& message_type, MessageCallback callback);
774
780 void once(const std::string& message_type, MessageCallback callback);
781
786 void off(const std::string& message_type);
787
794 void send(const std::string& message_type, const nlohmann::json& data, SendCallback callback = nullptr);
795
803 void send(const std::string& peer_id, const std::string& message_type, const nlohmann::json& data, SendCallback callback = nullptr);
804
805 // =========================================================================
806 // Encryption Functionality
807 // =========================================================================
808
814 bool initialize_encryption(bool enable);
815
820 void set_encryption_enabled(bool enabled);
821
827
833 bool is_peer_encrypted(const std::string& peer_id) const;
834
841 bool set_noise_static_keypair(const uint8_t private_key[32]);
842
847 std::vector<uint8_t> get_noise_static_public_key() const;
848
854 std::vector<uint8_t> get_peer_noise_public_key(const std::string& peer_id) const;
855
861 std::vector<uint8_t> get_peer_handshake_hash(const std::string& peer_id) const;
862
863 // =========================================================================
864 // Configuration Persistence
865 // =========================================================================
866
872
878
884 bool set_data_directory(const std::string& directory_path);
885
890 std::string get_data_directory() const;
891
897
903
909
914
919 std::vector<RatsPeer> get_historical_peers() const;
920
921 // =========================================================================
922 // Statistics and Information
923 // =========================================================================
924
929 nlohmann::json get_connection_statistics() const;
930
931 // =========================================================================
932 // GossipSub Functionality
933 // =========================================================================
934
940
946
947 // Topic Management
953 bool subscribe_to_topic(const std::string& topic);
954
960 bool unsubscribe_from_topic(const std::string& topic);
961
967 bool is_subscribed_to_topic(const std::string& topic) const;
968
973 std::vector<std::string> get_subscribed_topics() const;
974
975 // Publishing
982 bool publish_to_topic(const std::string& topic, const std::string& message);
983
990 bool publish_json_to_topic(const std::string& topic, const nlohmann::json& message);
991
992 // Event Handlers (Unified API)
998 void on_topic_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const std::string&)> callback);
999
1005 void on_topic_json_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const nlohmann::json&)> callback);
1006
1012 void on_topic_peer_joined(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback);
1013
1019 void on_topic_peer_left(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback);
1020
1026 void set_topic_message_validator(const std::string& topic, std::function<ValidationResult(const std::string&, const std::string&, const std::string&)> validator);
1027
1032 void off_topic(const std::string& topic);
1033
1034 // Information
1040 std::vector<std::string> get_topic_peers(const std::string& topic) const;
1041
1047 std::vector<std::string> get_topic_mesh_peers(const std::string& topic) const;
1048
1053 nlohmann::json get_gossipsub_statistics() const;
1054
1060
1061 // =========================================================================
1062 // Logging Control API
1063 // =========================================================================
1064
1072
1078
1084 void set_logging_enabled(bool enabled);
1085
1091
1096 void set_log_file_path(const std::string& file_path);
1097
1102 std::string get_log_file_path() const;
1103
1109
1114 void set_log_level(const std::string& level_str);
1115
1121
1126 void set_log_colors_enabled(bool enabled);
1127
1133
1138 void set_log_timestamps_enabled(bool enabled);
1139
1145
1150 void set_log_rotation_size(size_t max_size_bytes);
1151
1157
1164 void set_log_rotate_on_startup(bool enabled);
1165
1171
1176
1177 // =========================================================================
1178 // File Transfer API
1179 // =========================================================================
1180 //
1181 // Streams files and directory trees to connected peers. A transfer is
1182 // offered to the peer, who accepts (choosing a destination) or rejects it.
1183 // See file_transfer.h for the FileTransferManager that implements it.
1184
1189
1194
1202 std::string send_file(const std::string& peer_id, const std::string& file_path,
1203 const std::string& remote_filename = "");
1204
1212 std::string send_directory(const std::string& peer_id, const std::string& directory_path,
1213 const std::string& remote_name = "");
1214
1219 bool accept_file_transfer(const std::string& transfer_id, const std::string& local_path);
1220
1224 bool reject_file_transfer(const std::string& transfer_id, const std::string& reason = "");
1225
1227 bool pause_file_transfer(const std::string& transfer_id);
1228
1230 bool resume_file_transfer(const std::string& transfer_id);
1231
1233 bool cancel_file_transfer(const std::string& transfer_id);
1234
1236 std::shared_ptr<FileTransferProgress> get_file_transfer_progress(const std::string& transfer_id) const;
1237
1239 std::vector<std::shared_ptr<FileTransferProgress>> get_active_file_transfers() const;
1240
1242 nlohmann::json get_file_transfer_statistics() const;
1243
1246
1249
1252
1255
1262
1263 // =========================================================================
1264 // ICE (NAT Traversal) API
1265 // =========================================================================
1266
1272
1277 bool is_ice_available() const;
1278
1279 // Server Configuration
1285 void add_stun_server(const std::string& host, uint16_t port = STUN_DEFAULT_PORT);
1286
1294 void add_turn_server(const std::string& host, uint16_t port,
1295 const std::string& username, const std::string& password);
1296
1301
1302 // Candidate Gathering
1309
1315 std::vector<IceCandidate> get_ice_candidates() const;
1316
1322
1323 // Public Address Discovery
1328 std::optional<std::pair<std::string, uint16_t>> get_public_address() const;
1329
1338 std::optional<StunMappedAddress> discover_public_address(
1339 const std::string& server = "stun.l.google.com",
1340 uint16_t port = 19302,
1341 int timeout_ms = 5000);
1342
1343 // Remote Candidates
1349
1354 void add_remote_ice_candidates_from_sdp(const std::vector<std::string>& sdp_lines);
1355
1360
1361 // Connectivity
1366
1372
1378
1383 bool is_ice_connected() const;
1384
1389 std::optional<IceCandidatePair> get_ice_selected_pair() const;
1390
1391 // ICE Event Callbacks
1397
1403
1409
1415
1421
1422 // ICE Configuration
1427 void set_ice_config(const IceConfig& config);
1428
1434
1435 // ICE Lifecycle
1440
1445
1446 // =========================================================================
1447 // Automatic Port Forwarding API (UPnP IGD + NAT-PMP)
1448 // =========================================================================
1449 //
1450 // When enabled (the default), RatsClient asks the home router to forward the
1451 // TCP listen port on startup, using UPnP and NAT-PMP in parallel (whichever
1452 // the router supports wins). Mappings are refreshed automatically and removed
1453 // on stop(). This lets peers behind a NAT accept inbound connections without
1454 // manual router configuration.
1455
1461 void set_port_mapping_enabled(bool enabled);
1462
1465
1467 void set_port_mapping_config(const PortMappingConfig& config);
1468
1470 PortMappingConfig get_port_mapping_config() const;
1471
1476 void add_port_mapping(PortMapProtocol protocol, uint16_t port);
1477
1482 std::optional<std::pair<std::string, uint16_t>> get_mapped_public_address() const;
1483
1488 void on_port_mapping(PortMapCallback callback);
1489
1490 // =========================================================================
1491 // Network change detection
1492 // =========================================================================
1493 //
1494 // A long-lived node must notice when the host's connectivity changes (a new
1495 // interface, an IP added/removed, the default route flipping between Wi-Fi
1496 // and cellular, dock/undock, VPN up/down, wake-from-sleep) and recover:
1497 // renew router port mappings, re-discover its public address via STUN, and
1498 // re-announce to the DHT. Otherwise it keeps advertising a stale endpoint
1499 // until the next periodic refresh. Enabled by default. Implemented in
1500 // librats_portmap.cpp on top of the platform-specific NetworkMonitor.
1501
1509
1518
1519#ifdef RATS_STORAGE
1520 // =========================================================================
1521 // Distributed Storage API (requires RATS_STORAGE)
1522 // =========================================================================
1523
1528 StorageManager& get_storage_manager();
1529
1535
1536 // Put Operations
1543 bool storage_put(const std::string& key, const std::string& value);
1544
1551 bool storage_put(const std::string& key, int64_t value);
1552
1559 bool storage_put(const std::string& key, double value);
1560
1567 bool storage_put(const std::string& key, const std::vector<uint8_t>& value);
1568
1575 bool storage_put_json(const std::string& key, const nlohmann::json& value);
1576
1577 // Get Operations
1583 std::optional<std::string> storage_get_string(const std::string& key) const;
1584
1590 std::optional<int64_t> storage_get_int(const std::string& key) const;
1591
1597 std::optional<double> storage_get_double(const std::string& key) const;
1598
1604 std::optional<std::vector<uint8_t>> storage_get_binary(const std::string& key) const;
1605
1611 std::optional<nlohmann::json> storage_get_json(const std::string& key) const;
1612
1613 // Delete and Query Operations
1619 bool storage_delete(const std::string& key);
1620
1626 bool storage_has(const std::string& key) const;
1627
1632 std::vector<std::string> storage_keys() const;
1633
1639 std::vector<std::string> storage_keys_with_prefix(const std::string& prefix) const;
1640
1645 size_t storage_size() const;
1646
1647 // Synchronization
1653
1658 bool is_storage_synced() const;
1659
1660 // Statistics
1665 nlohmann::json get_storage_statistics() const;
1666
1671 void set_storage_config(const StorageConfig& config);
1672
1677 const StorageConfig& get_storage_config() const;
1678
1679 // Event Handlers
1684 void on_storage_change(StorageChangeCallback callback);
1685
1690 void on_storage_sync_complete(StorageSyncCompleteCallback callback);
1691#endif // RATS_STORAGE
1692
1693#ifdef RATS_SEARCH_FEATURES
1694 // =========================================================================
1695 // BitTorrent API (requires RATS_SEARCH_FEATURES)
1696 // =========================================================================
1697
1703 bool enable_bittorrent(int listen_port = 6881);
1704
1711 void set_resume_data_path(const std::string& path);
1712
1717
1723
1730 std::shared_ptr<TorrentDownload> add_torrent(const std::string& torrent_file,
1731 const std::string& download_path);
1732
1739 std::shared_ptr<TorrentDownload> add_torrent(const TorrentInfo& torrent_info,
1740 const std::string& download_path);
1741
1749 std::shared_ptr<TorrentDownload> add_torrent_by_hash(const InfoHash& info_hash,
1750 const std::string& download_path);
1751
1759 std::shared_ptr<TorrentDownload> add_torrent_by_hash(const std::string& info_hash_hex,
1760 const std::string& download_path);
1761
1767 bool remove_torrent(const InfoHash& info_hash);
1768
1774 std::shared_ptr<TorrentDownload> get_torrent(const InfoHash& info_hash);
1775
1780 std::vector<std::shared_ptr<TorrentDownload>> get_all_torrents();
1781
1787
1792 std::pair<uint64_t, uint64_t> get_bittorrent_stats() const;
1793
1800 void get_torrent_metadata(const InfoHash& info_hash,
1801 std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1802
1809 void get_torrent_metadata(const std::string& info_hash_hex,
1810 std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1811
1822 const std::string& peer_ip,
1823 uint16_t peer_port,
1824 std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1825
1834 void get_torrent_metadata_from_peer(const std::string& info_hash_hex,
1835 const std::string& peer_ip,
1836 uint16_t peer_port,
1837 std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1838
1839 // =========================================================================
1840 // Torrent Creation API (requires RATS_SEARCH_FEATURES)
1841 // =========================================================================
1842
1849 using TorrentCreationProgressCallback = std::function<void(uint32_t current_piece, uint32_t total_pieces)>;
1850
1860 std::optional<TorrentInfo> create_torrent_from_path(
1861 const std::string& path,
1862 const std::vector<std::string>& trackers = {},
1863 const std::string& comment = "",
1864 TorrentCreationProgressCallback progress_callback = nullptr);
1865
1874 std::vector<uint8_t> create_torrent_data(
1875 const std::string& path,
1876 const std::vector<std::string>& trackers = {},
1877 const std::string& comment = "",
1878 TorrentCreationProgressCallback progress_callback = nullptr);
1879
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);
1895
1906 std::shared_ptr<TorrentDownload> create_and_seed_torrent(
1907 const std::string& path,
1908 const std::vector<std::string>& trackers = {},
1909 const std::string& comment = "",
1910 TorrentCreationProgressCallback progress_callback = nullptr);
1911
1912 // =========================================================================
1913 // Spider Mode API (requires RATS_SEARCH_FEATURES)
1914 // =========================================================================
1915
1922 using SpiderAnnounceCallback = std::function<void(const std::string& info_hash, const std::string& peer_address)>;
1923
1931 void set_spider_mode(bool enable);
1932
1937 bool is_spider_mode() const;
1938
1945
1951 void set_spider_ignore(bool ignore);
1952
1958
1965
1970 size_t get_spider_pool_size() const;
1971
1977
1983#endif // RATS_SEARCH_FEATURES
1984
1985private:
1986 int listen_port_;
1987 std::string bind_address_;
1988 int max_peers_;
1989 socket_t server_socket_;
1990 std::atomic<bool> running_;
1991
1992 // =========================================================================
1993 // MUTEX LOCKING ORDER - CRITICAL FOR DEADLOCK PREVENTION
1994 // =========================================================================
1995 // When acquiring multiple mutexes, ALWAYS follow this strict order:
1996 //
1997 // 1. config_mutex_ (Configuration and peer ID)
1998 // 2. protocol_config_mutex_ (Protocol name and version)
1999 // 3. encryption_mutex_ (Encryption settings and keys)
2000 // 4. local_addresses_mutex_ (Local interface addresses)
2001 // 5. peers_mutex_ (Peer management - most frequently locked)
2002 // 6. io_mutex_ (I/O poller and send buffer access)
2003 // 7. message_handlers_mutex_ (Message handler registration)
2004 // 8. reconnect_mutex_ (Reconnection queue management)
2005 // 9. port_mapping_mutex_ (UPnP/NAT-PMP backends and mapped address)
2006 // 10. network_monitor_mutex_ / network_recovery_mutex_ (network-change state)
2007 //
2008 // (9) and (10) are leaf locks: they are never held while acquiring any lock
2009 // above, so they impose no additional ordering constraints.
2010 // =========================================================================
2011
2012 // [1] Configuration persistence (protected by config_mutex_)
2013 mutable std::mutex config_mutex_; // [1] Protects configuration data
2014 std::string our_peer_id_; // Our persistent peer ID
2015 std::string data_directory_; // Directory where data files are stored
2016 static const std::string CONFIG_FILE_NAME; // "config.json"
2017 static const std::string PEERS_FILE_NAME; // "peers.rats"
2018 static const std::string PEERS_EVER_FILE_NAME; // "peers_ever.rats"
2019
2020 // [2] Custom protocol configuration (protected by protocol_config_mutex_)
2021 mutable std::mutex protocol_config_mutex_; // [2] Protects protocol configuration
2022 std::string custom_protocol_name_; // Custom protocol name (default: "rats")
2023 std::string custom_protocol_version_; // Custom protocol version (default: "1.0")
2024
2025 // [3] Encryption state (protected by encryption_mutex_)
2026 mutable std::mutex encryption_mutex_; // [3] Protects encryption state
2027 bool encryption_enabled_; // Whether encryption is enabled
2028 rats::NoiseKeyPair noise_static_keypair_; // Our static Noise keypair
2029 bool noise_keypair_initialized_; // Whether keypair has been initialized
2030
2031 // [4] Local interface address blocking (protected by local_addresses_mutex_)
2032 mutable std::mutex local_addresses_mutex_; // [4] Protects local interface addresses
2033 std::unordered_set<std::string> local_interface_addresses_;
2034 // Subset of local_interface_addresses_ that came from interface enumeration.
2035 // Tracked separately so a network-change refresh can drop only stale auto
2036 // entries without evicting localhost or externally-discovered addresses
2037 // (STUN reflexive, mapped external IP, user add_ignored_address()).
2038 std::unordered_set<std::string> auto_interface_addresses_;
2039
2040 // [5] Organized peer management using RatsPeer struct (protected by peers_mutex_)
2041 mutable std::mutex peers_mutex_; // [5] Protects peer data (most frequently locked)
2042 std::unordered_map<std::string, RatsPeer> peers_; // keyed by peer_id
2043 std::unordered_map<socket_t, std::string> socket_to_peer_id_; // for quick socket->peer_id lookup
2044 std::unordered_map<std::string, std::string> address_to_peer_id_; // for duplicate detection (normalized_address->peer_id)
2045 std::atomic<int> validated_peer_count_{0}; // Cached count of peers with COMPLETED handshake
2046
2047 // [6] Async I/O (poller + io thread)
2048 std::unique_ptr<IOPoller> poller_;
2049 std::mutex io_mutex_; // Protects poller_ and send-buffer writes from non-IO threads
2050 std::thread io_thread_;
2051 std::thread management_thread_;
2052
2053 ConnectionCallback connection_callback_;
2054 BinaryDataCallback binary_data_callback_;
2055 StringDataCallback string_data_callback_;
2056 JsonDataCallback json_data_callback_;
2057 DisconnectCallback disconnect_callback_;
2058
2059 // DHT clients for peer discovery. IPv4 and IPv6 are separate Kademlia networks
2060 // (BEP 32), so each family runs its own client. dht_client_ (IPv4) is also the one
2061 // shared with the BitTorrent subsystem; dht_client_v6_ is created best-effort when
2062 // IPv6 is available.
2063 std::unique_ptr<DhtClient> dht_client_;
2064 std::unique_ptr<DhtClient> dht_client_v6_;
2065
2066 // mDNS client for local network discovery
2067 std::unique_ptr<MdnsClient> mdns_client_;
2068 std::function<void(const std::string&, int, const std::string&)> mdns_callback_;
2069
2070 // GossipSub for publish-subscribe messaging
2071 std::unique_ptr<GossipSub> gossipsub_;
2072
2073 // File transfer manager
2074 std::unique_ptr<FileTransferManager> file_transfer_manager_;
2075
2076 // ICE manager for NAT traversal
2077 std::unique_ptr<IceManager> ice_manager_;
2078
2079 // Automatic port forwarding (UPnP IGD + NAT-PMP). Implemented in librats_portmap.cpp.
2080 mutable std::mutex port_mapping_mutex_; // guards the fields below
2081 PortMappingConfig port_mapping_config_;
2082 std::unique_ptr<UpnpClient> upnp_client_;
2083 std::unique_ptr<NatPmpClient> natpmp_client_;
2084 PortMapCallback port_mapping_callback_;
2085 // Public address discovered by the backends. The external port is tracked per
2086 // protocol (like libtorrent's per-listen-socket tcp/udp port mappings): the TCP
2087 // mapping forwards the peer listen port, the UDP mapping forwards the DHT port.
2088 // A single field would let the two backend callbacks clobber each other.
2089 std::string mapped_external_ip_;
2090 uint16_t mapped_external_tcp_port_ = 0; // public port for the TCP peer-listen port
2091 uint16_t mapped_external_udp_port_ = 0; // public port for the UDP DHT port
2092 // Set once we warn that the gateway's reported external IP is itself private
2093 // (double-NAT), so the warning isn't repeated on every lease refresh.
2094 bool double_nat_warning_logged_ = false;
2095
2096 // Start/stop the port mapping backends (no-ops if disabled). Called from
2097 // start()/stop(); safe to call repeatedly.
2098 void start_port_mapping();
2099 void stop_port_mapping();
2100 void handle_port_mapping_result(const PortMapResult& result);
2101 // Public TCP port to advertise to peers/DHT: the mapped external port once a
2102 // TCP mapping is established, otherwise the local listen port.
2103 uint16_t get_advertised_port() const;
2104
2105 // Network change detection (implemented in librats_portmap.cpp). Monitor runs
2106 // a platform watcher; on a real address-set change it refreshes the self-
2107 // address set inline and wakes the recovery worker, which re-maps ports,
2108 // re-discovers the public IP and re-announces. These mutexes are last in the
2109 // lock order (after [8]) and are never held while calling into other
2110 // subsystems, so they introduce no new ordering constraints.
2111 std::unique_ptr<NetworkMonitor> network_monitor_;
2112 bool network_change_detection_enabled_ = true; // start the monitor on start()
2113 mutable std::mutex network_monitor_mutex_; // guards the user callback below
2114 NetworkChangeCallback network_change_callback_;
2115 // Dedicated recovery worker: serialises the slow recovery work (STUN can
2116 // block for seconds) off the monitor thread and coalesces rapid changes.
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;
2122
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();
2128
2129#ifdef RATS_STORAGE
2130 // Distributed storage manager (optional, requires RATS_STORAGE)
2131 std::unique_ptr<StorageManager> storage_manager_;
2132#endif
2133
2134#ifdef RATS_SEARCH_FEATURES
2135 // BitTorrent client (optional, requires RATS_SEARCH_FEATURES)
2136 std::unique_ptr<BitTorrentClient> bittorrent_client_;
2137#endif
2138
2139 void initialize_modules();
2140 void destroy_modules();
2141
2142 // Async I/O loop (single thread for all sockets)
2143 void io_loop();
2144 void management_loop();
2145
2146 // I/O event handlers (called from io_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);
2151
2152 // Poller registration helpers
2153 void poller_add(socket_t fd, uint32_t events);
2154 void poller_modify(socket_t fd, uint32_t events);
2155 void poller_remove(socket_t fd);
2156
2157 // Helpers – post-handshake and message routing
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);
2160
2161 // Peer lookup helper (assumes peers_mutex_ is already locked)
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;
2164
2165 void remove_peer(socket_t socket);
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);
2169
2170 // Message header helpers
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;
2173
2174 // Peer management methods using RatsPeer
2175 void add_peer_unlocked(const RatsPeer& peer); // Assumes peers_mutex_ is already locked
2176 void remove_peer_by_id_unlocked(const std::string& peer_id); // Assumes peers_mutex_ is already locked
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;
2181
2182 // Async send – enqueues a framed (length-prefixed) message into the peer's
2183 // ChainedSendBuffer and arms PollOut. Thread-safe (acquires io_mutex_).
2184 // Returns false if the peer was not found.
2185 bool enqueue_message(socket_t socket, const std::vector<uint8_t>& data);
2186 // Unlocked variant – caller must hold peers_mutex_
2187 bool enqueue_message_unlocked(RatsPeer& peer, const std::vector<uint8_t>& data);
2188
2189 // Lightweight snapshot of peer data needed for sending (avoids holding peers_mutex_ during enqueue)
2190 struct PeerSendTarget {
2191 socket_t socket;
2192 std::string peer_id;
2193 std::shared_ptr<rats::NoiseCipherState> send_cipher;
2194 };
2195
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);
2200
2201 // Async Noise handshake – processes one Noise XX message received from peer.
2202 // Returns false if peer should be disconnected. Called from handle_readable.
2203 bool handle_noise_frame(RatsPeer& peer);
2204 // Kick-off: initialises noise_hs and writes first outgoing message if initiator.
2205 void start_noise_handshake_async(RatsPeer& peer);
2206
2207 // Local interface address blocking helper functions
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);
2213
2214 // Helper functions that assume mutex is already locked
2215 int get_peer_count_unlocked() const; // Helper that assumes peers_mutex_ is already locked
2216
2217 // Protocol constants
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; // 10 second TCP connection timeout
2221 static constexpr int IO_POLL_TIMEOUT_MS = 100; // IO poller tick interval (ms)
2222 static constexpr size_t MAX_FRAME_SIZE = 100 * 1024 * 1024; // 100 MB max single frame
2223 static constexpr int PEER_RECONNECT_DELAY_MS = 100; // Delay before reconnecting saved peers
2224 static constexpr int HISTORICAL_RECONNECT_DELAY_MS = 500; // Delay before reconnecting historical peers
2225 static constexpr int MANAGEMENT_LOOP_INTERVAL_SECONDS = 2; // Management loop tick interval
2226 static constexpr int THREAD_CLEANUP_INTERVAL_SECONDS = 30; // Thread cleanup interval
2227 static constexpr int INITIAL_DISCOVERY_DELAY_SECONDS = 5; // DHT bootstrap delay
2228 static constexpr int MAX_PEERS_REQUEST_COUNT = 5; // Max peers to request/respond
2229 static constexpr int CONTENT_HASH_HEX_LENGTH = 40; // 160-bit hash as hex
2230 static constexpr int64_t TIMESTAMP_SKEW_TOLERANCE_MS = 10LL * 60LL * 1000LL; // 10 minutes
2231
2232 struct HandshakeMessage {
2233 std::string protocol;
2234 std::string version;
2235 std::string peer_id;
2236 std::string message_type;
2237 int64_t timestamp;
2238 bool encryption_enabled; // Whether peer supports/wants encryption
2239 uint16_t listen_port; // Peer's listening port for peer exchange
2240 };
2241
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); // enqueues via send buffer (peers_mutex_ held)
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);
2250
2251 // Automatic discovery
2252 std::atomic<bool> auto_discovery_running_;
2253 std::thread auto_discovery_thread_;
2254 void automatic_discovery_loop();
2255 void announce_rats_peer();
2256
2257 // Message handling system
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);
2260
2261 // Specific message handlers
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);
2265
2266 // Message creation and broadcasting
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);
2273
2274 int broadcast_rats_message(const nlohmann::json& message, const std::string& exclude_peer_id = "", bool validated_only = true);
2275
2276 // [7] Message exchange API implementation (protected by message_handlers_mutex_)
2277 mutable std::mutex message_handlers_mutex_; // [7] Protects message handlers
2278 struct MessageHandler {
2279 MessageCallback callback;
2280 bool is_once;
2281
2282 MessageHandler(MessageCallback cb, bool once) : callback(cb), is_once(once) {}
2283 };
2284 std::unordered_map<std::string, std::vector<MessageHandler>> message_handlers_;
2285
2286 void call_message_handlers(const std::string& message_type, const std::string& peer_id, const nlohmann::json& data);
2287
2288 // [8] Automatic reconnection system (protected by reconnect_mutex_)
2289 mutable std::mutex reconnect_mutex_; // [8] Protects reconnection queue
2290 std::unordered_map<std::string, ReconnectInfo> reconnect_queue_; // keyed by peer_id
2291 ReconnectConfig reconnect_config_; // Reconnection configuration
2292 std::unordered_set<std::string> manual_disconnect_peers_; // Peers that were manually disconnected (don't reconnect)
2293
2294 // Reconnection helper methods
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;
2299
2300 // Configuration persistence helpers
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();
2310
2311 // Noise Protocol encryption helpers
2312 void initialize_noise_keypair();
2313};
2314
2315// Utility functions
2316std::unique_ptr<RatsClient> create_rats_client(int listen_port);
2317
2318// Library version query (stable, binding-friendly)
2319RATS_API const char* rats_get_library_version_string();
2320RATS_API void rats_get_library_version(int* major, int* minor, int* patch, int* build);
2321RATS_API const char* rats_get_library_git_describe();
2322RATS_API uint32_t rats_get_library_abi(); // packed as (major<<16)|(minor<<8)|patch
2323
2324} // namespace librats
Main GossipSub implementation class.
Definition gossipsub.h:167
ICE-lite Manager for NAT traversal.
Definition ice.h:321
RatsClient - Core peer-to-peer networking client.
Definition librats.h:278
std::function< void(socket_t, const std::string &, const std::vector< uint8_t > &)> BinaryDataCallback
Definition librats.h:284
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
Definition librats.h:286
std::function< void(bool, const std::string &)> SendCallback
Definition librats.h:289
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
Definition librats.h:287
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
Definition librats.h:293
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...
Definition librats.h:1922
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.
Definition librats.h:1849
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
Definition librats.h:283
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
Definition librats.h:285
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
~RatsClient()
Destructor.
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
Definition librats.h:288
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.
LogLevel
Definition logger.h:28
IceGatheringState
ICE gathering state.
Definition ice.h:87
std::function< void(IceGatheringState)> IceGatheringStateCallback
Callback when gathering state changes.
Definition ice.h:263
std::function< void(const std::string &topic, const std::string &message, const std::string &sender_peer_id)> MessageHandler
Definition gossipsub.h:160
MessageDataType
Message data types for librats message headers.
Definition librats.h:204
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)
Definition ice.h:269
std::function< void(const std::vector< IceCandidate > &)> IceCandidatesCallback
Callback when candidates are gathered.
Definition ice.h:260
std::function< void(IceConnectionState)> IceConnectionStateCallback
Callback when connection state changes.
Definition ice.h:266
std::function< void(const IceCandidatePair &)> IceSelectedPairCallback
Callback when ICE completes with selected pair.
Definition ice.h:272
ValidationResult
Message validation result.
Definition gossipsub.h:150
std::unique_ptr< RatsClient > create_rats_client(int listen_port)
std::array< uint8_t, NODE_ID_SIZE > InfoHash
Definition dht.h:51
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.
Definition ice.h:73
int socket_t
Definition socket.h:22
ICE candidate.
Definition ice.h:96
ICE configuration.
Definition ice.h:226
Message header structure for librats messages Fixed 8-byte header format: [0-3]: Magic number "RATS" ...
Definition librats.h:217
MessageDataType type
Definition librats.h:222
bool is_valid_type() const
Definition librats.h:268
static bool deserialize(const std::vector< uint8_t > &data, MessageHeader &header)
Definition librats.h:246
MessageHeader(MessageDataType data_type)
Definition librats.h:225
static constexpr uint32_t MAGIC_NUMBER
Definition librats.h:218
static constexpr size_t HEADER_SIZE
Definition librats.h:219
uint8_t reserved[3]
Definition librats.h:223
std::vector< uint8_t > serialize() const
Definition librats.h:234
PeerIOContext - Per-peer async I/O buffers and framing state.
Definition librats.h:55
std::unique_ptr< rats::NoiseHandshakeState > noise_hs
Definition librats.h:60
ChainedSendBuffer send_buffer
Definition librats.h:57
ReceiveBuffer recv_buffer
Definition librats.h:56
RatsPeer struct - comprehensive information about a connected rats peer.
Definition librats.h:67
std::string ip
Definition librats.h:69
socket_t socket
Definition librats.h:71
bool encryption_enabled
Definition librats.h:90
std::shared_ptr< rats::NoiseCipherState > recv_cipher
Definition librats.h:93
std::vector< uint8_t > remote_static_key
Definition librats.h:94
RatsPeer(const RatsPeer &o)
Definition librats.h:119
bool is_noise_encrypted() const
Definition librats.h:157
PeerIOContext io_
Definition librats.h:97
RatsPeer(RatsPeer &&)=default
std::shared_ptr< rats::NoiseCipherState > send_cipher
Definition librats.h:92
bool is_handshake_completed() const
Definition librats.h:162
bool noise_handshake_completed
Definition librats.h:91
std::string peer_id
Definition librats.h:68
HandshakeState handshake_state
Definition librats.h:85
RatsPeer & operator=(const RatsPeer &o)
Definition librats.h:130
RatsPeer(const std::string &id, const std::string &peer_ip, uint16_t peer_port, socket_t sock, const std::string &norm_addr, bool outgoing)
Definition librats.h:106
RatsPeer & operator=(RatsPeer &&)=default
bool is_handshake_failed() const
Definition librats.h:163
std::chrono::steady_clock::time_point handshake_start_time
Definition librats.h:87
std::string normalized_address
Definition librats.h:72
uint16_t port
Definition librats.h:70
std::string version
Definition librats.h:86
std::chrono::steady_clock::time_point connected_at
Definition librats.h:73
ReconnectConfig - Configuration for automatic peer reconnection.
Definition librats.h:169
std::vector< int > retry_intervals_seconds
Definition librats.h:171
int stable_connection_threshold_seconds
Definition librats.h:172
ReconnectInfo - Information about a peer pending reconnection.
Definition librats.h:180
ReconnectInfo(const std::string &id, const std::string &peer_ip, uint16_t peer_port, std::chrono::milliseconds duration, bool stable)
Definition librats.h:193
std::chrono::milliseconds connection_duration
Definition librats.h:186
std::string peer_id
Definition librats.h:181
std::chrono::steady_clock::time_point next_attempt_time
Definition librats.h:185