librats 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +1 -0
- package/native-src/3rdparty/android/ifaddrs-android.c +600 -0
- package/native-src/3rdparty/android/ifaddrs-android.h +54 -0
- package/native-src/CMakeLists.txt +360 -0
- package/native-src/LICENSE +21 -0
- package/native-src/src/bencode.cpp +485 -0
- package/native-src/src/bencode.h +145 -0
- package/native-src/src/bittorrent.cpp +3682 -0
- package/native-src/src/bittorrent.h +731 -0
- package/native-src/src/dht.cpp +2342 -0
- package/native-src/src/dht.h +501 -0
- package/native-src/src/encrypted_socket.cpp +817 -0
- package/native-src/src/encrypted_socket.h +239 -0
- package/native-src/src/file_transfer.cpp +1808 -0
- package/native-src/src/file_transfer.h +567 -0
- package/native-src/src/fs.cpp +639 -0
- package/native-src/src/fs.h +108 -0
- package/native-src/src/gossipsub.cpp +1137 -0
- package/native-src/src/gossipsub.h +403 -0
- package/native-src/src/ice.cpp +1386 -0
- package/native-src/src/ice.h +328 -0
- package/native-src/src/json.hpp +25526 -0
- package/native-src/src/krpc.cpp +558 -0
- package/native-src/src/krpc.h +145 -0
- package/native-src/src/librats.cpp +2715 -0
- package/native-src/src/librats.h +1729 -0
- package/native-src/src/librats_bittorrent.cpp +167 -0
- package/native-src/src/librats_c.cpp +1317 -0
- package/native-src/src/librats_c.h +237 -0
- package/native-src/src/librats_encryption.cpp +123 -0
- package/native-src/src/librats_file_transfer.cpp +226 -0
- package/native-src/src/librats_gossipsub.cpp +293 -0
- package/native-src/src/librats_ice.cpp +515 -0
- package/native-src/src/librats_logging.cpp +158 -0
- package/native-src/src/librats_mdns.cpp +171 -0
- package/native-src/src/librats_nat.cpp +571 -0
- package/native-src/src/librats_persistence.cpp +815 -0
- package/native-src/src/logger.h +412 -0
- package/native-src/src/mdns.cpp +1178 -0
- package/native-src/src/mdns.h +253 -0
- package/native-src/src/network_utils.cpp +598 -0
- package/native-src/src/network_utils.h +162 -0
- package/native-src/src/noise.cpp +981 -0
- package/native-src/src/noise.h +227 -0
- package/native-src/src/os.cpp +371 -0
- package/native-src/src/os.h +40 -0
- package/native-src/src/rats_export.h +17 -0
- package/native-src/src/sha1.cpp +163 -0
- package/native-src/src/sha1.h +42 -0
- package/native-src/src/socket.cpp +1376 -0
- package/native-src/src/socket.h +309 -0
- package/native-src/src/stun.cpp +484 -0
- package/native-src/src/stun.h +349 -0
- package/native-src/src/threadmanager.cpp +105 -0
- package/native-src/src/threadmanager.h +53 -0
- package/native-src/src/tracker.cpp +1110 -0
- package/native-src/src/tracker.h +268 -0
- package/native-src/src/version.cpp +24 -0
- package/native-src/src/version.h.in +45 -0
- package/native-src/version.rc.in +31 -0
- package/package.json +2 -8
- package/scripts/build-librats.js +59 -12
- package/scripts/prepare-package.js +133 -37
|
@@ -0,0 +1,1729 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "socket.h"
|
|
4
|
+
#include "dht.h"
|
|
5
|
+
#include "stun.h"
|
|
6
|
+
#include "mdns.h"
|
|
7
|
+
#include "ice.h"
|
|
8
|
+
#include "logger.h"
|
|
9
|
+
#include "encrypted_socket.h"
|
|
10
|
+
#include "threadmanager.h"
|
|
11
|
+
#include "gossipsub.h" // For ValidationResult enum and GossipSub types
|
|
12
|
+
#include "file_transfer.h" // File transfer functionality
|
|
13
|
+
#ifdef RATS_SEARCH_FEATURES
|
|
14
|
+
#include "bittorrent.h" // BitTorrent functionality (optional, requires RATS_SEARCH_FEATURES)
|
|
15
|
+
#endif
|
|
16
|
+
#include "json.hpp" // nlohmann::json
|
|
17
|
+
#include <string>
|
|
18
|
+
#include <functional>
|
|
19
|
+
#include <thread>
|
|
20
|
+
#include <vector>
|
|
21
|
+
#include <mutex>
|
|
22
|
+
#include <atomic>
|
|
23
|
+
#include <unordered_map>
|
|
24
|
+
#include <memory>
|
|
25
|
+
#include <chrono>
|
|
26
|
+
#include <condition_variable>
|
|
27
|
+
#include <unordered_set> // Added for unordered_set
|
|
28
|
+
#include <cstdint>
|
|
29
|
+
#include <cstring>
|
|
30
|
+
#include "rats_export.h"
|
|
31
|
+
|
|
32
|
+
namespace librats {
|
|
33
|
+
|
|
34
|
+
// Forward declarations
|
|
35
|
+
class IceAgent;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* RatsPeer struct - comprehensive information about a connected rats peer
|
|
39
|
+
*/
|
|
40
|
+
struct RatsPeer {
|
|
41
|
+
std::string peer_id; // Unique hash ID for the peer
|
|
42
|
+
std::string ip; // IP address
|
|
43
|
+
uint16_t port; // Port number
|
|
44
|
+
socket_t socket; // Socket handle
|
|
45
|
+
std::string normalized_address; // Normalized address for duplicate detection (ip:port)
|
|
46
|
+
std::chrono::steady_clock::time_point connected_at; // Connection timestamp
|
|
47
|
+
bool is_outgoing; // True if we initiated the connection, false if incoming
|
|
48
|
+
|
|
49
|
+
// Handshake-related fields
|
|
50
|
+
enum class HandshakeState {
|
|
51
|
+
PENDING, // Handshake not started
|
|
52
|
+
SENT, // Handshake sent, waiting for response
|
|
53
|
+
COMPLETED, // Handshake completed successfully
|
|
54
|
+
FAILED // Handshake failed
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
HandshakeState handshake_state; // Current handshake state
|
|
58
|
+
std::string version; // Protocol version of remote peer
|
|
59
|
+
int peer_count; // Number of peers connected to remote peer
|
|
60
|
+
std::chrono::steady_clock::time_point handshake_start_time; // When handshake started
|
|
61
|
+
|
|
62
|
+
// Encryption-related fields
|
|
63
|
+
bool encryption_enabled; // Whether encryption is enabled for this peer
|
|
64
|
+
bool noise_handshake_completed; // Whether noise handshake is completed
|
|
65
|
+
NoiseKey remote_static_key; // Remote peer's static public key (after handshake)
|
|
66
|
+
|
|
67
|
+
// NAT traversal fields
|
|
68
|
+
bool ice_enabled; // Whether ICE is enabled for this peer
|
|
69
|
+
std::string ice_ufrag; // ICE username fragment
|
|
70
|
+
std::string ice_pwd; // ICE password
|
|
71
|
+
std::vector<IceCandidate> ice_candidates; // ICE candidates for this peer
|
|
72
|
+
IceConnectionState ice_state; // Current ICE connection state
|
|
73
|
+
NatType detected_nat_type; // Detected NAT type for this peer
|
|
74
|
+
std::string connection_method; // How connection was established (direct, stun, turn, ice)
|
|
75
|
+
|
|
76
|
+
// Connection quality metrics
|
|
77
|
+
uint32_t rtt_ms; // Round-trip time in milliseconds
|
|
78
|
+
uint32_t packet_loss_percent; // Packet loss percentage
|
|
79
|
+
std::string transport_protocol; // UDP, TCP, etc.
|
|
80
|
+
|
|
81
|
+
RatsPeer() : handshake_state(HandshakeState::PENDING),
|
|
82
|
+
peer_count(0), encryption_enabled(false), noise_handshake_completed(false),
|
|
83
|
+
ice_enabled(false), ice_state(IceConnectionState::NEW),
|
|
84
|
+
detected_nat_type(NatType::UNKNOWN), rtt_ms(0), packet_loss_percent(0),
|
|
85
|
+
transport_protocol("UDP") {
|
|
86
|
+
connected_at = std::chrono::steady_clock::now();
|
|
87
|
+
handshake_start_time = connected_at;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
RatsPeer(const std::string& id, const std::string& peer_ip, uint16_t peer_port,
|
|
91
|
+
socket_t sock, const std::string& norm_addr, bool outgoing)
|
|
92
|
+
: peer_id(id), ip(peer_ip), port(peer_port), socket(sock),
|
|
93
|
+
normalized_address(norm_addr), is_outgoing(outgoing),
|
|
94
|
+
handshake_state(HandshakeState::PENDING), peer_count(0),
|
|
95
|
+
encryption_enabled(false), noise_handshake_completed(false),
|
|
96
|
+
ice_enabled(false), ice_state(IceConnectionState::NEW),
|
|
97
|
+
detected_nat_type(NatType::UNKNOWN), rtt_ms(0), packet_loss_percent(0),
|
|
98
|
+
transport_protocol("UDP") {
|
|
99
|
+
connected_at = std::chrono::steady_clock::now();
|
|
100
|
+
handshake_start_time = connected_at;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Helper methods
|
|
104
|
+
bool is_handshake_completed() const { return handshake_state == HandshakeState::COMPLETED; }
|
|
105
|
+
bool is_handshake_failed() const { return handshake_state == HandshakeState::FAILED; }
|
|
106
|
+
bool is_ice_connected() const {
|
|
107
|
+
return ice_state == IceConnectionState::CONNECTED ||
|
|
108
|
+
ice_state == IceConnectionState::COMPLETED;
|
|
109
|
+
}
|
|
110
|
+
bool is_fully_connected() const {
|
|
111
|
+
return is_handshake_completed() && (!ice_enabled || is_ice_connected());
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// NAT Traversal Configuration
|
|
116
|
+
struct NatTraversalConfig {
|
|
117
|
+
bool enable_ice; // Enable ICE for NAT traversal
|
|
118
|
+
bool enable_upnp; // Enable UPnP for port mapping
|
|
119
|
+
bool enable_hole_punching; // Enable UDP/TCP hole punching
|
|
120
|
+
bool enable_turn_relay; // Enable TURN relay as last resort
|
|
121
|
+
bool prefer_ipv6; // Prefer IPv6 connections when available
|
|
122
|
+
|
|
123
|
+
// ICE configuration
|
|
124
|
+
std::vector<std::string> stun_servers;
|
|
125
|
+
std::vector<std::string> turn_servers;
|
|
126
|
+
std::vector<std::string> turn_usernames;
|
|
127
|
+
std::vector<std::string> turn_passwords;
|
|
128
|
+
|
|
129
|
+
// Timeouts and limits
|
|
130
|
+
int ice_gathering_timeout_ms;
|
|
131
|
+
int ice_connectivity_timeout_ms;
|
|
132
|
+
int hole_punch_attempts;
|
|
133
|
+
int turn_allocation_timeout_ms;
|
|
134
|
+
|
|
135
|
+
// Priority settings
|
|
136
|
+
int host_candidate_priority;
|
|
137
|
+
int server_reflexive_priority;
|
|
138
|
+
int relay_candidate_priority;
|
|
139
|
+
|
|
140
|
+
NatTraversalConfig()
|
|
141
|
+
: enable_ice(true), enable_upnp(false), enable_hole_punching(true),
|
|
142
|
+
enable_turn_relay(true), prefer_ipv6(false),
|
|
143
|
+
ice_gathering_timeout_ms(10000), ice_connectivity_timeout_ms(30000),
|
|
144
|
+
hole_punch_attempts(5), turn_allocation_timeout_ms(10000),
|
|
145
|
+
host_candidate_priority(65535), server_reflexive_priority(65534),
|
|
146
|
+
relay_candidate_priority(65533) {
|
|
147
|
+
|
|
148
|
+
// Default STUN servers
|
|
149
|
+
stun_servers.push_back("stun.l.google.com:19302");
|
|
150
|
+
stun_servers.push_back("stun1.l.google.com:19302");
|
|
151
|
+
stun_servers.push_back("stun.stunprotocol.org:3478");
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Connection establishment strategies
|
|
156
|
+
enum class ConnectionStrategy {
|
|
157
|
+
DIRECT_ONLY, // Try direct connection only
|
|
158
|
+
STUN_ASSISTED, // Use STUN for public IP discovery
|
|
159
|
+
ICE_FULL, // Full ICE with candidate gathering
|
|
160
|
+
TURN_RELAY, // Force TURN relay usage
|
|
161
|
+
AUTO_ADAPTIVE // Automatically choose best strategy
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Connection attempt result
|
|
165
|
+
struct ConnectionAttemptResult {
|
|
166
|
+
bool success;
|
|
167
|
+
std::string method; // "direct", "stun", "ice", "turn", "hole_punch"
|
|
168
|
+
std::chrono::milliseconds duration;
|
|
169
|
+
std::string error_message;
|
|
170
|
+
NatType local_nat_type;
|
|
171
|
+
NatType remote_nat_type;
|
|
172
|
+
std::vector<IceCandidate> used_candidates;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// Enhanced connection callbacks
|
|
176
|
+
using AdvancedConnectionCallback = std::function<void(socket_t, const std::string&, const ConnectionAttemptResult&)>;
|
|
177
|
+
using NatTraversalProgressCallback = std::function<void(const std::string&, const std::string&)>; // peer_id, status
|
|
178
|
+
using IceCandidateDiscoveredCallback = std::function<void(const std::string&, const IceCandidate&)>; // peer_id, candidate
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Message data types for librats message headers
|
|
182
|
+
*/
|
|
183
|
+
enum class MessageDataType : uint8_t {
|
|
184
|
+
BINARY = 0x01, // Raw binary data
|
|
185
|
+
STRING = 0x02, // UTF-8 string data
|
|
186
|
+
JSON = 0x03 // JSON formatted data
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Message header structure for librats messages
|
|
191
|
+
* Fixed 8-byte header format:
|
|
192
|
+
* [0-3]: Magic number "RATS" (4 bytes)
|
|
193
|
+
* [4]: Message data type (1 byte)
|
|
194
|
+
* [5-7]: Reserved for future use (3 bytes)
|
|
195
|
+
*/
|
|
196
|
+
struct MessageHeader {
|
|
197
|
+
static constexpr uint32_t MAGIC_NUMBER = 0x52415453; // "RATS" in ASCII
|
|
198
|
+
static constexpr size_t HEADER_SIZE = 8;
|
|
199
|
+
|
|
200
|
+
uint32_t magic; // Magic number for validation
|
|
201
|
+
MessageDataType type; // Message data type
|
|
202
|
+
uint8_t reserved[3]; // Reserved bytes for future use
|
|
203
|
+
|
|
204
|
+
MessageHeader(MessageDataType data_type) : magic(MAGIC_NUMBER), type(data_type) {
|
|
205
|
+
reserved[0] = reserved[1] = reserved[2] = 0;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
MessageHeader() : magic(MAGIC_NUMBER), type(MessageDataType::BINARY) {
|
|
209
|
+
reserved[0] = reserved[1] = reserved[2] = 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Serialize header to bytes
|
|
213
|
+
std::vector<uint8_t> serialize() const {
|
|
214
|
+
std::vector<uint8_t> data(HEADER_SIZE);
|
|
215
|
+
uint32_t network_magic = htonl(magic);
|
|
216
|
+
memcpy(data.data(), &network_magic, 4);
|
|
217
|
+
data[4] = static_cast<uint8_t>(type);
|
|
218
|
+
data[5] = reserved[0];
|
|
219
|
+
data[6] = reserved[1];
|
|
220
|
+
data[7] = reserved[2];
|
|
221
|
+
return data;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Deserialize header from bytes
|
|
225
|
+
static bool deserialize(const std::vector<uint8_t>& data, MessageHeader& header) {
|
|
226
|
+
if (data.size() < HEADER_SIZE) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
uint32_t network_magic;
|
|
231
|
+
memcpy(&network_magic, data.data(), 4);
|
|
232
|
+
header.magic = ntohl(network_magic);
|
|
233
|
+
|
|
234
|
+
if (header.magic != MAGIC_NUMBER) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
header.type = static_cast<MessageDataType>(data[4]);
|
|
239
|
+
header.reserved[0] = data[5];
|
|
240
|
+
header.reserved[1] = data[6];
|
|
241
|
+
header.reserved[2] = data[7];
|
|
242
|
+
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Validate data type
|
|
247
|
+
bool is_valid_type() const {
|
|
248
|
+
return type == MessageDataType::BINARY ||
|
|
249
|
+
type == MessageDataType::STRING ||
|
|
250
|
+
type == MessageDataType::JSON;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Enhanced RatsClient with comprehensive NAT traversal capabilities
|
|
256
|
+
*/
|
|
257
|
+
class RATS_API RatsClient : public ThreadManager {
|
|
258
|
+
public:
|
|
259
|
+
// =========================================================================
|
|
260
|
+
// Type Definitions and Callbacks
|
|
261
|
+
// =========================================================================
|
|
262
|
+
using ConnectionCallback = std::function<void(socket_t, const std::string&)>;
|
|
263
|
+
using BinaryDataCallback = std::function<void(socket_t, const std::string&, const std::vector<uint8_t>&)>;
|
|
264
|
+
using StringDataCallback = std::function<void(socket_t, const std::string&, const std::string&)>;
|
|
265
|
+
using JsonDataCallback = std::function<void(socket_t, const std::string&, const nlohmann::json&)>;
|
|
266
|
+
using DisconnectCallback = std::function<void(socket_t, const std::string&)>;
|
|
267
|
+
using MessageCallback = std::function<void(const std::string&, const nlohmann::json&)>;
|
|
268
|
+
using SendCallback = std::function<void(bool, const std::string&)>;
|
|
269
|
+
|
|
270
|
+
// =========================================================================
|
|
271
|
+
// Constructor and Destructor
|
|
272
|
+
// =========================================================================
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Constructor
|
|
276
|
+
* @param listen_port Port to listen on for incoming connections
|
|
277
|
+
* @param max_peers Maximum number of concurrent peers (default: 10)
|
|
278
|
+
* @param nat_config NAT traversal configuration
|
|
279
|
+
* @param bind_address Interface IP address to bind to (empty for all interfaces)
|
|
280
|
+
*/
|
|
281
|
+
RatsClient(int listen_port, int max_peers = 10, const NatTraversalConfig& nat_config = NatTraversalConfig(), const std::string& bind_address = "");
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Destructor
|
|
285
|
+
*/
|
|
286
|
+
~RatsClient();
|
|
287
|
+
|
|
288
|
+
// =========================================================================
|
|
289
|
+
// Core Lifecycle Management
|
|
290
|
+
// =========================================================================
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Start the RatsClient and begin listening for connections
|
|
294
|
+
* @return true if successful, false otherwise
|
|
295
|
+
*/
|
|
296
|
+
bool start();
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Stop the RatsClient and close all connections
|
|
300
|
+
*/
|
|
301
|
+
void stop();
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Shutdown all background threads
|
|
305
|
+
*/
|
|
306
|
+
void shutdown_all_threads();
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Check if the client is currently running
|
|
310
|
+
* @return true if running, false otherwise
|
|
311
|
+
*/
|
|
312
|
+
bool is_running() const;
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
// =========================================================================
|
|
316
|
+
// Utility Methods
|
|
317
|
+
// =========================================================================
|
|
318
|
+
|
|
319
|
+
int get_listen_port() const;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get the bind address being used
|
|
323
|
+
* @return Bind address (empty string if binding to all interfaces)
|
|
324
|
+
*/
|
|
325
|
+
std::string get_bind_address() const;
|
|
326
|
+
|
|
327
|
+
// =========================================================================
|
|
328
|
+
// Connection Management
|
|
329
|
+
// =========================================================================
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Connect to a peer with automatic NAT traversal
|
|
333
|
+
* @param host Target host/IP address
|
|
334
|
+
* @param port Target port
|
|
335
|
+
* @param strategy Connection strategy to use
|
|
336
|
+
* @return true if connection initiated successfully
|
|
337
|
+
*/
|
|
338
|
+
bool connect_to_peer(const std::string& host, int port,
|
|
339
|
+
ConnectionStrategy strategy = ConnectionStrategy::AUTO_ADAPTIVE);
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Connect to a peer using ICE coordination
|
|
343
|
+
* @param peer_id Target peer ID
|
|
344
|
+
* @param ice_offer ICE offer from remote peer
|
|
345
|
+
* @return true if ICE connection initiated successfully
|
|
346
|
+
*/
|
|
347
|
+
bool connect_with_ice(const std::string& peer_id, const nlohmann::json& ice_offer);
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Create ICE offer for a peer
|
|
351
|
+
* @param peer_id Target peer ID
|
|
352
|
+
* @return ICE offer JSON that can be sent to the peer
|
|
353
|
+
*/
|
|
354
|
+
nlohmann::json create_ice_offer(const std::string& peer_id);
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Handle ICE answer from a peer
|
|
358
|
+
* @param peer_id Source peer ID
|
|
359
|
+
* @param ice_answer ICE answer from the peer
|
|
360
|
+
* @return true if successfully processed
|
|
361
|
+
*/
|
|
362
|
+
bool handle_ice_answer(const std::string& peer_id, const nlohmann::json& ice_answer);
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Disconnect from a specific peer
|
|
366
|
+
* @param socket Peer socket to disconnect
|
|
367
|
+
*/
|
|
368
|
+
void disconnect_peer(socket_t socket);
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Disconnect from a peer by peer_id (preferred)
|
|
372
|
+
* @param peer_id Peer ID to disconnect
|
|
373
|
+
*/
|
|
374
|
+
void disconnect_peer_by_id(const std::string& peer_id);
|
|
375
|
+
|
|
376
|
+
// =========================================================================
|
|
377
|
+
// Data Transmission Methods
|
|
378
|
+
// =========================================================================
|
|
379
|
+
|
|
380
|
+
// Send to specific peer by socket
|
|
381
|
+
/**
|
|
382
|
+
* Send binary data to a specific peer (primary method)
|
|
383
|
+
* @param socket Target peer socket
|
|
384
|
+
* @param data Binary data to send
|
|
385
|
+
* @param message_type Type of message data (BINARY, STRING, JSON)
|
|
386
|
+
* @return true if sent successfully
|
|
387
|
+
*/
|
|
388
|
+
bool send_binary_to_peer(socket_t socket, const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Send string data to a specific peer
|
|
392
|
+
* @param socket Target peer socket
|
|
393
|
+
* @param data String data to send
|
|
394
|
+
* @return true if sent successfully
|
|
395
|
+
*/
|
|
396
|
+
bool send_string_to_peer(socket_t socket, const std::string& data);
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Send JSON data to a specific peer
|
|
400
|
+
* @param socket Target peer socket
|
|
401
|
+
* @param data JSON data to send
|
|
402
|
+
* @return true if sent successfully
|
|
403
|
+
*/
|
|
404
|
+
bool send_json_to_peer(socket_t socket, const nlohmann::json& data);
|
|
405
|
+
|
|
406
|
+
// Send to specific peer by ID
|
|
407
|
+
/**
|
|
408
|
+
* Send binary data to a peer by peer_id (preferred)
|
|
409
|
+
* @param peer_id Target peer ID
|
|
410
|
+
* @param data Binary data to send
|
|
411
|
+
* @param message_type Type of message data (BINARY, STRING, JSON)
|
|
412
|
+
* @return true if sent successfully
|
|
413
|
+
*/
|
|
414
|
+
bool send_binary_to_peer_id(const std::string& peer_id, const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Send string data to a peer by peer_id (preferred)
|
|
418
|
+
* @param peer_id Target peer ID
|
|
419
|
+
* @param data String data to send
|
|
420
|
+
* @return true if sent successfully
|
|
421
|
+
*/
|
|
422
|
+
bool send_string_to_peer_id(const std::string& peer_id, const std::string& data);
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Send JSON data to a peer by peer_id (preferred)
|
|
426
|
+
* @param peer_id Target peer ID
|
|
427
|
+
* @param data JSON data to send
|
|
428
|
+
* @return true if sent successfully
|
|
429
|
+
*/
|
|
430
|
+
bool send_json_to_peer_id(const std::string& peer_id, const nlohmann::json& data);
|
|
431
|
+
|
|
432
|
+
// Broadcast to all peers
|
|
433
|
+
/**
|
|
434
|
+
* Broadcast binary data to all connected peers (primary method)
|
|
435
|
+
* @param data Binary data to broadcast
|
|
436
|
+
* @param message_type Type of message data (BINARY, STRING, JSON)
|
|
437
|
+
* @return Number of peers the data was sent to
|
|
438
|
+
*/
|
|
439
|
+
int broadcast_binary_to_peers(const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Broadcast string data to all connected peers
|
|
443
|
+
* @param data String data to broadcast
|
|
444
|
+
* @return Number of peers the data was sent to
|
|
445
|
+
*/
|
|
446
|
+
int broadcast_string_to_peers(const std::string& data);
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Broadcast JSON data to all connected peers
|
|
450
|
+
* @param data JSON data to broadcast
|
|
451
|
+
* @return Number of peers the data was sent to
|
|
452
|
+
*/
|
|
453
|
+
int broadcast_json_to_peers(const nlohmann::json& data);
|
|
454
|
+
|
|
455
|
+
// =========================================================================
|
|
456
|
+
// Peer Information and Management
|
|
457
|
+
// =========================================================================
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Get the number of currently connected peers
|
|
461
|
+
* @return Number of connected peers
|
|
462
|
+
*/
|
|
463
|
+
int get_peer_count() const;
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Get peer_id for a peer by socket (preferred)
|
|
468
|
+
* @param socket Peer socket
|
|
469
|
+
* @return Peer ID or empty string if not found
|
|
470
|
+
*/
|
|
471
|
+
std::string get_peer_id(socket_t socket) const;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Get socket for a peer by peer_id (preferred)
|
|
475
|
+
* @param peer_id Peer ID
|
|
476
|
+
* @return Peer socket or INVALID_SOCKET_VALUE if not found
|
|
477
|
+
*/
|
|
478
|
+
socket_t get_peer_socket_by_id(const std::string& peer_id) const;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Get our own peer ID
|
|
482
|
+
* @return Our persistent peer ID
|
|
483
|
+
*/
|
|
484
|
+
std::string get_our_peer_id() const;
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Get all connected peers
|
|
488
|
+
* @return Vector of RatsPeer objects
|
|
489
|
+
*/
|
|
490
|
+
std::vector<RatsPeer> get_all_peers() const;
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Get all peers that have completed handshake
|
|
494
|
+
* @return Vector of RatsPeer objects with completed handshake
|
|
495
|
+
*/
|
|
496
|
+
std::vector<RatsPeer> get_validated_peers() const;
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Get peer information by peer ID
|
|
500
|
+
* @param peer_id The peer ID to look up
|
|
501
|
+
* @return Pointer to RatsPeer object, or nullptr if not found
|
|
502
|
+
*/
|
|
503
|
+
const RatsPeer* get_peer_by_id(const std::string& peer_id) const;
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Get peer information by socket
|
|
507
|
+
* @param socket The socket handle to look up
|
|
508
|
+
* @return Pointer to RatsPeer object, or nullptr if not found
|
|
509
|
+
*/
|
|
510
|
+
const RatsPeer* get_peer_by_socket(socket_t socket) const;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Get maximum number of peers
|
|
514
|
+
* @return Maximum peer count
|
|
515
|
+
*/
|
|
516
|
+
int get_max_peers() const;
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Set maximum number of peers
|
|
520
|
+
* @param max_peers New maximum peer count
|
|
521
|
+
*/
|
|
522
|
+
void set_max_peers(int max_peers);
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Check if peer limit has been reached
|
|
526
|
+
* @return true if at limit, false otherwise
|
|
527
|
+
*/
|
|
528
|
+
bool is_peer_limit_reached() const;
|
|
529
|
+
|
|
530
|
+
// =========================================================================
|
|
531
|
+
// Callback Registration
|
|
532
|
+
// =========================================================================
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Set connection callback (called when a new peer connects)
|
|
536
|
+
* @param callback Function to call on new connections
|
|
537
|
+
*/
|
|
538
|
+
void set_connection_callback(ConnectionCallback callback);
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Set advanced connection callback with NAT traversal info
|
|
542
|
+
* @param callback Function to call on new connections with detailed info
|
|
543
|
+
*/
|
|
544
|
+
void set_advanced_connection_callback(AdvancedConnectionCallback callback);
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Set binary data callback (called when binary data is received)
|
|
548
|
+
* @param callback Function to call when binary data is received
|
|
549
|
+
*/
|
|
550
|
+
void set_binary_data_callback(BinaryDataCallback callback);
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Set string data callback (called when string data is received)
|
|
554
|
+
* @param callback Function to call when string data is received
|
|
555
|
+
*/
|
|
556
|
+
void set_string_data_callback(StringDataCallback callback);
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Set JSON data callback (called when JSON data is received)
|
|
560
|
+
* @param callback Function to call when JSON data is received
|
|
561
|
+
*/
|
|
562
|
+
void set_json_data_callback(JsonDataCallback callback);
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Set disconnect callback (called when a peer disconnects)
|
|
566
|
+
* @param callback Function to call on disconnections
|
|
567
|
+
*/
|
|
568
|
+
void set_disconnect_callback(DisconnectCallback callback);
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Set NAT traversal progress callback
|
|
572
|
+
* @param callback Function to call with NAT traversal progress updates
|
|
573
|
+
*/
|
|
574
|
+
void set_nat_traversal_progress_callback(NatTraversalProgressCallback callback);
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Set ICE candidate discovered callback
|
|
578
|
+
* @param callback Function to call when ICE candidates are discovered
|
|
579
|
+
*/
|
|
580
|
+
void set_ice_candidate_callback(IceCandidateDiscoveredCallback callback);
|
|
581
|
+
|
|
582
|
+
// =========================================================================
|
|
583
|
+
// Peer Discovery Methods
|
|
584
|
+
// =========================================================================
|
|
585
|
+
|
|
586
|
+
// DHT Discovery
|
|
587
|
+
/**
|
|
588
|
+
* Start DHT discovery on specified port
|
|
589
|
+
* @param dht_port Port for DHT communication (default: 6881)
|
|
590
|
+
* @return true if started successfully
|
|
591
|
+
*/
|
|
592
|
+
bool start_dht_discovery(int dht_port = 6881);
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Stop DHT discovery
|
|
596
|
+
*/
|
|
597
|
+
void stop_dht_discovery();
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Find peers by content hash using DHT
|
|
601
|
+
* @param content_hash Hash to search for (40-character hex string)
|
|
602
|
+
* @param callback Function to call with discovered peers
|
|
603
|
+
* @return true if search initiated successfully
|
|
604
|
+
*/
|
|
605
|
+
bool find_peers_by_hash(const std::string& content_hash,
|
|
606
|
+
std::function<void(const std::vector<std::string>&)> callback);
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Announce our presence for a content hash
|
|
610
|
+
* @param content_hash Hash to announce for (40-character hex string)
|
|
611
|
+
* @param port Port to announce (default: our listen port)
|
|
612
|
+
* @return true if announced successfully
|
|
613
|
+
*/
|
|
614
|
+
bool announce_for_hash(const std::string& content_hash, uint16_t port = 0);
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Check if DHT is currently running
|
|
618
|
+
* @return true if DHT is running
|
|
619
|
+
*/
|
|
620
|
+
bool is_dht_running() const;
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Get the size of the DHT routing table
|
|
624
|
+
* @return Number of nodes in routing table
|
|
625
|
+
*/
|
|
626
|
+
size_t get_dht_routing_table_size() const;
|
|
627
|
+
|
|
628
|
+
// mDNS Discovery
|
|
629
|
+
/**
|
|
630
|
+
* Start mDNS service discovery and announcement
|
|
631
|
+
* @param service_instance_name Service instance name (optional)
|
|
632
|
+
* @param txt_records Additional TXT records for service announcement
|
|
633
|
+
* @return true if started successfully
|
|
634
|
+
*/
|
|
635
|
+
bool start_mdns_discovery(const std::string& service_instance_name = "",
|
|
636
|
+
const std::map<std::string, std::string>& txt_records = {});
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Stop mDNS discovery
|
|
640
|
+
*/
|
|
641
|
+
void stop_mdns_discovery();
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Check if mDNS is currently running
|
|
645
|
+
* @return true if mDNS is running
|
|
646
|
+
*/
|
|
647
|
+
bool is_mdns_running() const;
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Set mDNS service discovery callback
|
|
651
|
+
* @param callback Function to call when services are discovered
|
|
652
|
+
*/
|
|
653
|
+
void set_mdns_callback(std::function<void(const std::string&, int, const std::string&)> callback);
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Get recently discovered mDNS services
|
|
657
|
+
* @return Vector of discovered services
|
|
658
|
+
*/
|
|
659
|
+
std::vector<MdnsService> get_mdns_services() const;
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Manually query for mDNS services
|
|
663
|
+
* @return true if query sent successfully
|
|
664
|
+
*/
|
|
665
|
+
bool query_mdns_services();
|
|
666
|
+
|
|
667
|
+
// Automatic Discovery
|
|
668
|
+
/**
|
|
669
|
+
* Start automatic peer discovery
|
|
670
|
+
*/
|
|
671
|
+
void start_automatic_peer_discovery();
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Stop automatic peer discovery
|
|
675
|
+
*/
|
|
676
|
+
void stop_automatic_peer_discovery();
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Check if automatic discovery is running
|
|
680
|
+
* @return true if automatic discovery is running
|
|
681
|
+
*/
|
|
682
|
+
bool is_automatic_discovery_running() const;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Get the discovery hash for current protocol configuration
|
|
686
|
+
* @return Discovery hash based on current protocol name and version
|
|
687
|
+
*/
|
|
688
|
+
std::string get_discovery_hash() const;
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Get the well-known RATS peer discovery hash
|
|
692
|
+
* @return Standard RATS discovery hash
|
|
693
|
+
*/
|
|
694
|
+
static std::string get_rats_peer_discovery_hash();
|
|
695
|
+
|
|
696
|
+
// =========================================================================
|
|
697
|
+
// NAT Traversal and STUN Functionality
|
|
698
|
+
// =========================================================================
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Discover public IP address using STUN and add to ignore list
|
|
702
|
+
* @param stun_server STUN server hostname (default: Google STUN)
|
|
703
|
+
* @param stun_port STUN server port (default: 19302)
|
|
704
|
+
* @return true if successful, false otherwise
|
|
705
|
+
*/
|
|
706
|
+
bool discover_and_ignore_public_ip(const std::string& stun_server = "stun.l.google.com", int stun_port = 19302);
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Detect NAT type using STUN servers
|
|
710
|
+
* @return Detected NAT type
|
|
711
|
+
*/
|
|
712
|
+
NatType detect_nat_type();
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Get detailed NAT characteristics
|
|
716
|
+
* @return Detailed NAT information
|
|
717
|
+
*/
|
|
718
|
+
NatTypeInfo get_nat_characteristics();
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Get the discovered public IP address
|
|
722
|
+
* @return Public IP address string or empty if not discovered
|
|
723
|
+
*/
|
|
724
|
+
std::string get_public_ip() const;
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Add an IP address to the ignore list
|
|
728
|
+
* @param ip_address IP address to ignore
|
|
729
|
+
*/
|
|
730
|
+
void add_ignored_address(const std::string& ip_address);
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Perform coordinated hole punching with a peer
|
|
734
|
+
* @param peer_ip Peer IP address
|
|
735
|
+
* @param peer_port Peer port
|
|
736
|
+
* @param coordination_data Coordination data from peer
|
|
737
|
+
* @return true if successful
|
|
738
|
+
*/
|
|
739
|
+
bool coordinate_hole_punching(const std::string& peer_ip, uint16_t peer_port,
|
|
740
|
+
const nlohmann::json& coordination_data);
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Get NAT traversal statistics
|
|
744
|
+
* @return JSON object with NAT traversal statistics
|
|
745
|
+
*/
|
|
746
|
+
nlohmann::json get_nat_traversal_statistics() const;
|
|
747
|
+
|
|
748
|
+
// =========================================================================
|
|
749
|
+
// Protocol Configuration
|
|
750
|
+
// =========================================================================
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Set custom protocol name for handshakes and DHT discovery
|
|
754
|
+
* @param protocol_name Custom protocol name (default: "rats")
|
|
755
|
+
*/
|
|
756
|
+
void set_protocol_name(const std::string& protocol_name);
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Set custom protocol version for handshakes
|
|
760
|
+
* @param protocol_version Custom protocol version (default: "1.0")
|
|
761
|
+
*/
|
|
762
|
+
void set_protocol_version(const std::string& protocol_version);
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Get current protocol name
|
|
766
|
+
* @return Current protocol name
|
|
767
|
+
*/
|
|
768
|
+
std::string get_protocol_name() const;
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Get current protocol version
|
|
772
|
+
* @return Current protocol version
|
|
773
|
+
*/
|
|
774
|
+
std::string get_protocol_version() const;
|
|
775
|
+
|
|
776
|
+
// =========================================================================
|
|
777
|
+
// Message Exchange API
|
|
778
|
+
// =========================================================================
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Register a persistent message handler
|
|
782
|
+
* @param message_type Type of message to handle
|
|
783
|
+
* @param callback Function to call when message is received
|
|
784
|
+
*/
|
|
785
|
+
void on(const std::string& message_type, MessageCallback callback);
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Register a one-time message handler
|
|
789
|
+
* @param message_type Type of message to handle
|
|
790
|
+
* @param callback Function to call when message is received (once only)
|
|
791
|
+
*/
|
|
792
|
+
void once(const std::string& message_type, MessageCallback callback);
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Remove all handlers for a message type
|
|
796
|
+
* @param message_type Type of message to stop handling
|
|
797
|
+
*/
|
|
798
|
+
void off(const std::string& message_type);
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Send a message to all peers
|
|
802
|
+
* @param message_type Type of message
|
|
803
|
+
* @param data Message data
|
|
804
|
+
* @param callback Optional callback for send result
|
|
805
|
+
*/
|
|
806
|
+
void send(const std::string& message_type, const nlohmann::json& data, SendCallback callback = nullptr);
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Send a message to a specific peer
|
|
810
|
+
* @param peer_id Target peer ID
|
|
811
|
+
* @param message_type Type of message
|
|
812
|
+
* @param data Message data
|
|
813
|
+
* @param callback Optional callback for send result
|
|
814
|
+
*/
|
|
815
|
+
void send(const std::string& peer_id, const std::string& message_type, const nlohmann::json& data, SendCallback callback = nullptr);
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Parse a JSON message
|
|
819
|
+
* @param message Raw message string
|
|
820
|
+
* @param out_json Parsed JSON output
|
|
821
|
+
* @return true if parsed successfully
|
|
822
|
+
*/
|
|
823
|
+
bool parse_json_message(const std::string& message, nlohmann::json& out_json);
|
|
824
|
+
|
|
825
|
+
// =========================================================================
|
|
826
|
+
// Encryption Functionality
|
|
827
|
+
// =========================================================================
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* Initialize encryption system
|
|
831
|
+
* @param enable Whether to enable encryption
|
|
832
|
+
* @return true if successful
|
|
833
|
+
*/
|
|
834
|
+
bool initialize_encryption(bool enable);
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Set encryption enabled/disabled
|
|
838
|
+
* @param enabled Whether encryption should be enabled
|
|
839
|
+
*/
|
|
840
|
+
void set_encryption_enabled(bool enabled);
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Check if encryption is enabled
|
|
844
|
+
* @return true if encryption is enabled
|
|
845
|
+
*/
|
|
846
|
+
bool is_encryption_enabled() const;
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Get the encryption key as hex string
|
|
850
|
+
* @return Encryption key in hex format
|
|
851
|
+
*/
|
|
852
|
+
std::string get_encryption_key() const;
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Set encryption key from hex string
|
|
856
|
+
* @param key_hex Encryption key in hex format
|
|
857
|
+
* @return true if key was valid and set
|
|
858
|
+
*/
|
|
859
|
+
bool set_encryption_key(const std::string& key_hex);
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Generate a new encryption key
|
|
863
|
+
* @return New encryption key in hex format
|
|
864
|
+
*/
|
|
865
|
+
std::string generate_new_encryption_key();
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Check if a peer connection is encrypted
|
|
869
|
+
* @param peer_id Peer ID to check
|
|
870
|
+
* @return true if peer connection is encrypted
|
|
871
|
+
*/
|
|
872
|
+
bool is_peer_encrypted(const std::string& peer_id) const;
|
|
873
|
+
|
|
874
|
+
// =========================================================================
|
|
875
|
+
// Configuration Persistence
|
|
876
|
+
// =========================================================================
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Load configuration from files
|
|
880
|
+
* @return true if successful, false otherwise
|
|
881
|
+
*/
|
|
882
|
+
bool load_configuration();
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Save configuration to files
|
|
886
|
+
* @return true if successful, false otherwise
|
|
887
|
+
*/
|
|
888
|
+
bool save_configuration();
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Set directory where data files will be stored
|
|
892
|
+
* @param directory_path Path to directory (default: current folder)
|
|
893
|
+
* @return true if directory is accessible, false otherwise
|
|
894
|
+
*/
|
|
895
|
+
bool set_data_directory(const std::string& directory_path);
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Get current data directory path
|
|
899
|
+
* @return Current data directory path
|
|
900
|
+
*/
|
|
901
|
+
std::string get_data_directory() const;
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Load saved peers and attempt to reconnect
|
|
905
|
+
* @return Number of connection attempts made
|
|
906
|
+
*/
|
|
907
|
+
int load_and_reconnect_peers();
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Load historical peers from a file
|
|
911
|
+
* @return true if successful, false otherwise
|
|
912
|
+
*/
|
|
913
|
+
bool load_historical_peers();
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Save current peers to a historical file
|
|
917
|
+
* @return true if successful, false otherwise
|
|
918
|
+
*/
|
|
919
|
+
bool save_historical_peers();
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* Clear all historical peers
|
|
923
|
+
*/
|
|
924
|
+
void clear_historical_peers();
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Get all historical peers
|
|
928
|
+
* @return Vector of RatsPeer objects
|
|
929
|
+
*/
|
|
930
|
+
std::vector<RatsPeer> get_historical_peers() const;
|
|
931
|
+
|
|
932
|
+
// =========================================================================
|
|
933
|
+
// Statistics and Information
|
|
934
|
+
// =========================================================================
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* Get connection statistics
|
|
938
|
+
* @return JSON object with detailed statistics
|
|
939
|
+
*/
|
|
940
|
+
nlohmann::json get_connection_statistics() const;
|
|
941
|
+
|
|
942
|
+
// =========================================================================
|
|
943
|
+
// GossipSub Functionality
|
|
944
|
+
// =========================================================================
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Get GossipSub instance for publish-subscribe messaging
|
|
948
|
+
* @return Reference to GossipSub instance
|
|
949
|
+
*/
|
|
950
|
+
GossipSub& get_gossipsub();
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* Check if GossipSub is available
|
|
954
|
+
* @return true if GossipSub is initialized
|
|
955
|
+
*/
|
|
956
|
+
bool is_gossipsub_available() const;
|
|
957
|
+
|
|
958
|
+
// Topic Management
|
|
959
|
+
/**
|
|
960
|
+
* Subscribe to a GossipSub topic
|
|
961
|
+
* @param topic Topic name to subscribe to
|
|
962
|
+
* @return true if subscription successful
|
|
963
|
+
*/
|
|
964
|
+
bool subscribe_to_topic(const std::string& topic);
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Unsubscribe from a GossipSub topic
|
|
968
|
+
* @param topic Topic name to unsubscribe from
|
|
969
|
+
* @return true if unsubscription successful
|
|
970
|
+
*/
|
|
971
|
+
bool unsubscribe_from_topic(const std::string& topic);
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Check if subscribed to a GossipSub topic
|
|
975
|
+
* @param topic Topic name to check
|
|
976
|
+
* @return true if subscribed
|
|
977
|
+
*/
|
|
978
|
+
bool is_subscribed_to_topic(const std::string& topic) const;
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Get list of subscribed GossipSub topics
|
|
982
|
+
* @return Vector of topic names
|
|
983
|
+
*/
|
|
984
|
+
std::vector<std::string> get_subscribed_topics() const;
|
|
985
|
+
|
|
986
|
+
// Publishing
|
|
987
|
+
/**
|
|
988
|
+
* Publish a message to a GossipSub topic
|
|
989
|
+
* @param topic Topic to publish to
|
|
990
|
+
* @param message Message content
|
|
991
|
+
* @return true if published successfully
|
|
992
|
+
*/
|
|
993
|
+
bool publish_to_topic(const std::string& topic, const std::string& message);
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* Publish a JSON message to a GossipSub topic
|
|
997
|
+
* @param topic Topic to publish to
|
|
998
|
+
* @param message JSON message content
|
|
999
|
+
* @return true if published successfully
|
|
1000
|
+
*/
|
|
1001
|
+
bool publish_json_to_topic(const std::string& topic, const nlohmann::json& message);
|
|
1002
|
+
|
|
1003
|
+
// Event Handlers (Unified API)
|
|
1004
|
+
/**
|
|
1005
|
+
* Set a message handler for a GossipSub topic using unified event API pattern
|
|
1006
|
+
* @param topic Topic name
|
|
1007
|
+
* @param callback Function to call when messages are received (peer_id, topic, message_content)
|
|
1008
|
+
*/
|
|
1009
|
+
void on_topic_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const std::string&)> callback);
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Set a JSON message handler for a GossipSub topic using unified event API pattern
|
|
1013
|
+
* @param topic Topic name
|
|
1014
|
+
* @param callback Function to call when JSON messages are received (peer_id, topic, json_message)
|
|
1015
|
+
*/
|
|
1016
|
+
void on_topic_json_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const nlohmann::json&)> callback);
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Set a peer joined handler for a GossipSub topic using unified event API pattern
|
|
1020
|
+
* @param topic Topic name
|
|
1021
|
+
* @param callback Function to call when peers join the topic
|
|
1022
|
+
*/
|
|
1023
|
+
void on_topic_peer_joined(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback);
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* Set a peer left handler for a GossipSub topic using unified event API pattern
|
|
1027
|
+
* @param topic Topic name
|
|
1028
|
+
* @param callback Function to call when peers leave the topic
|
|
1029
|
+
*/
|
|
1030
|
+
void on_topic_peer_left(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback);
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Set a message validator for a GossipSub topic
|
|
1034
|
+
* @param topic Topic name (empty for global validator)
|
|
1035
|
+
* @param validator Validation function returning ACCEPT, REJECT, or IGNORE_MSG
|
|
1036
|
+
*/
|
|
1037
|
+
void set_topic_message_validator(const std::string& topic, std::function<ValidationResult(const std::string&, const std::string&, const std::string&)> validator);
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Remove all event handlers for a GossipSub topic
|
|
1041
|
+
* @param topic Topic name
|
|
1042
|
+
*/
|
|
1043
|
+
void off_topic(const std::string& topic);
|
|
1044
|
+
|
|
1045
|
+
// Information
|
|
1046
|
+
/**
|
|
1047
|
+
* Get peers subscribed to a GossipSub topic
|
|
1048
|
+
* @param topic Topic name
|
|
1049
|
+
* @return Vector of peer IDs
|
|
1050
|
+
*/
|
|
1051
|
+
std::vector<std::string> get_topic_peers(const std::string& topic) const;
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Get mesh peers for a GossipSub topic
|
|
1055
|
+
* @param topic Topic name
|
|
1056
|
+
* @return Vector of peer IDs in the mesh
|
|
1057
|
+
*/
|
|
1058
|
+
std::vector<std::string> get_topic_mesh_peers(const std::string& topic) const;
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Get GossipSub statistics
|
|
1062
|
+
* @return JSON object with comprehensive GossipSub statistics
|
|
1063
|
+
*/
|
|
1064
|
+
nlohmann::json get_gossipsub_statistics() const;
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Check if GossipSub is running
|
|
1068
|
+
* @return true if GossipSub service is active
|
|
1069
|
+
*/
|
|
1070
|
+
bool is_gossipsub_running() const;
|
|
1071
|
+
|
|
1072
|
+
// =========================================================================
|
|
1073
|
+
// Logging Control API
|
|
1074
|
+
// =========================================================================
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Enable or disable file logging
|
|
1078
|
+
* When enabled, logs will be written to "rats.log" by default
|
|
1079
|
+
* @param enabled Whether to enable file logging
|
|
1080
|
+
*/
|
|
1081
|
+
void set_logging_enabled(bool enabled);
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* Check if file logging is currently enabled
|
|
1085
|
+
* @return true if file logging is enabled
|
|
1086
|
+
*/
|
|
1087
|
+
bool is_logging_enabled() const;
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Set the log file path
|
|
1091
|
+
* @param file_path Path to the log file (default: "rats.log")
|
|
1092
|
+
*/
|
|
1093
|
+
void set_log_file_path(const std::string& file_path);
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* Get the current log file path
|
|
1097
|
+
* @return Current log file path
|
|
1098
|
+
*/
|
|
1099
|
+
std::string get_log_file_path() const;
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Set the minimum log level
|
|
1103
|
+
* @param level Minimum log level (DEBUG=0, INFO=1, WARN=2, ERROR=3)
|
|
1104
|
+
*/
|
|
1105
|
+
void set_log_level(LogLevel level);
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Set the minimum log level using string
|
|
1109
|
+
* @param level_str Log level as string ("DEBUG", "INFO", "WARN", "ERROR")
|
|
1110
|
+
*/
|
|
1111
|
+
void set_log_level(const std::string& level_str);
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Get the current log level
|
|
1115
|
+
* @return Current minimum log level
|
|
1116
|
+
*/
|
|
1117
|
+
LogLevel get_log_level() const;
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Enable or disable colored log output
|
|
1121
|
+
* @param enabled Whether to enable colored output
|
|
1122
|
+
*/
|
|
1123
|
+
void set_log_colors_enabled(bool enabled);
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Check if colored log output is enabled
|
|
1127
|
+
* @return true if colors are enabled
|
|
1128
|
+
*/
|
|
1129
|
+
bool is_log_colors_enabled() const;
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Enable or disable timestamps in log output
|
|
1133
|
+
* @param enabled Whether to enable timestamps
|
|
1134
|
+
*/
|
|
1135
|
+
void set_log_timestamps_enabled(bool enabled);
|
|
1136
|
+
|
|
1137
|
+
/**
|
|
1138
|
+
* Check if timestamps are enabled in log output
|
|
1139
|
+
* @return true if timestamps are enabled
|
|
1140
|
+
*/
|
|
1141
|
+
bool is_log_timestamps_enabled() const;
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Set log file rotation size
|
|
1145
|
+
* @param max_size_bytes Maximum size in bytes before log rotation (default: 10MB)
|
|
1146
|
+
*/
|
|
1147
|
+
void set_log_rotation_size(size_t max_size_bytes);
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Set the number of log files to retain during rotation
|
|
1151
|
+
* @param count Number of old log files to keep (default: 5)
|
|
1152
|
+
*/
|
|
1153
|
+
void set_log_retention_count(int count);
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
* Clear/reset the current log file
|
|
1157
|
+
*/
|
|
1158
|
+
void clear_log_file();
|
|
1159
|
+
|
|
1160
|
+
// =========================================================================
|
|
1161
|
+
// File Transfer API
|
|
1162
|
+
// =========================================================================
|
|
1163
|
+
|
|
1164
|
+
/**
|
|
1165
|
+
* Get the file transfer manager instance
|
|
1166
|
+
* @return Reference to the file transfer manager
|
|
1167
|
+
*/
|
|
1168
|
+
FileTransferManager& get_file_transfer_manager();
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Check if file transfer is available
|
|
1172
|
+
* @return true if file transfer manager is initialized
|
|
1173
|
+
*/
|
|
1174
|
+
bool is_file_transfer_available() const;
|
|
1175
|
+
|
|
1176
|
+
// Sending and Requesting
|
|
1177
|
+
/**
|
|
1178
|
+
* Send a file to a peer
|
|
1179
|
+
* @param peer_id Target peer ID
|
|
1180
|
+
* @param file_path Local file path to send
|
|
1181
|
+
* @param remote_filename Optional remote filename (default: use local name)
|
|
1182
|
+
* @return Transfer ID if successful, empty string if failed
|
|
1183
|
+
*/
|
|
1184
|
+
std::string send_file(const std::string& peer_id, const std::string& file_path,
|
|
1185
|
+
const std::string& remote_filename = "");
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Send an entire directory to a peer
|
|
1189
|
+
* @param peer_id Target peer ID
|
|
1190
|
+
* @param directory_path Local directory path to send
|
|
1191
|
+
* @param remote_directory_name Optional remote directory name
|
|
1192
|
+
* @param recursive Whether to include subdirectories (default: true)
|
|
1193
|
+
* @return Transfer ID if successful, empty string if failed
|
|
1194
|
+
*/
|
|
1195
|
+
std::string send_directory(const std::string& peer_id, const std::string& directory_path,
|
|
1196
|
+
const std::string& remote_directory_name = "", bool recursive = true);
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* Request a file from a remote peer
|
|
1200
|
+
* @param peer_id Target peer ID
|
|
1201
|
+
* @param remote_file_path Path to file on remote peer
|
|
1202
|
+
* @param local_path Local path where file should be saved
|
|
1203
|
+
* @return Transfer ID if successful, empty string if failed
|
|
1204
|
+
*/
|
|
1205
|
+
std::string request_file(const std::string& peer_id, const std::string& remote_file_path,
|
|
1206
|
+
const std::string& local_path);
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Request a directory from a remote peer
|
|
1210
|
+
* @param peer_id Target peer ID
|
|
1211
|
+
* @param remote_directory_path Path to directory on remote peer
|
|
1212
|
+
* @param local_directory_path Local path where directory should be saved
|
|
1213
|
+
* @param recursive Whether to include subdirectories (default: true)
|
|
1214
|
+
* @return Transfer ID if successful, empty string if failed
|
|
1215
|
+
*/
|
|
1216
|
+
std::string request_directory(const std::string& peer_id, const std::string& remote_directory_path,
|
|
1217
|
+
const std::string& local_directory_path, bool recursive = true);
|
|
1218
|
+
|
|
1219
|
+
// Accept/Reject Operations
|
|
1220
|
+
/**
|
|
1221
|
+
* Accept an incoming file transfer
|
|
1222
|
+
* @param transfer_id Transfer identifier from request
|
|
1223
|
+
* @param local_path Local path where file should be saved
|
|
1224
|
+
* @return true if accepted successfully
|
|
1225
|
+
*/
|
|
1226
|
+
bool accept_file_transfer(const std::string& transfer_id, const std::string& local_path);
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Reject an incoming file transfer
|
|
1230
|
+
* @param transfer_id Transfer identifier from request
|
|
1231
|
+
* @param reason Optional reason for rejection
|
|
1232
|
+
* @return true if rejected successfully
|
|
1233
|
+
*/
|
|
1234
|
+
bool reject_file_transfer(const std::string& transfer_id, const std::string& reason = "");
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* Accept an incoming directory transfer
|
|
1238
|
+
* @param transfer_id Transfer identifier from request
|
|
1239
|
+
* @param local_path Local path where directory should be saved
|
|
1240
|
+
* @return true if accepted successfully
|
|
1241
|
+
*/
|
|
1242
|
+
bool accept_directory_transfer(const std::string& transfer_id, const std::string& local_path);
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Reject an incoming directory transfer
|
|
1246
|
+
* @param transfer_id Transfer identifier from request
|
|
1247
|
+
* @param reason Optional reason for rejection
|
|
1248
|
+
* @return true if rejected successfully
|
|
1249
|
+
*/
|
|
1250
|
+
bool reject_directory_transfer(const std::string& transfer_id, const std::string& reason = "");
|
|
1251
|
+
|
|
1252
|
+
// Transfer Control
|
|
1253
|
+
/**
|
|
1254
|
+
* Pause an active file transfer
|
|
1255
|
+
* @param transfer_id Transfer to pause
|
|
1256
|
+
* @return true if paused successfully
|
|
1257
|
+
*/
|
|
1258
|
+
bool pause_file_transfer(const std::string& transfer_id);
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Resume a paused file transfer
|
|
1262
|
+
* @param transfer_id Transfer to resume
|
|
1263
|
+
* @return true if resumed successfully
|
|
1264
|
+
*/
|
|
1265
|
+
bool resume_file_transfer(const std::string& transfer_id);
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* Cancel an active or paused file transfer
|
|
1269
|
+
* @param transfer_id Transfer to cancel
|
|
1270
|
+
* @return true if cancelled successfully
|
|
1271
|
+
*/
|
|
1272
|
+
bool cancel_file_transfer(const std::string& transfer_id);
|
|
1273
|
+
|
|
1274
|
+
// Information and Monitoring
|
|
1275
|
+
/**
|
|
1276
|
+
* Get file transfer progress information
|
|
1277
|
+
* @param transfer_id Transfer to query
|
|
1278
|
+
* @return Progress information or nullptr if not found
|
|
1279
|
+
*/
|
|
1280
|
+
std::shared_ptr<FileTransferProgress> get_file_transfer_progress(const std::string& transfer_id) const;
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Get all active file transfers
|
|
1284
|
+
* @return Vector of transfer progress objects
|
|
1285
|
+
*/
|
|
1286
|
+
std::vector<std::shared_ptr<FileTransferProgress>> get_active_file_transfers() const;
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Get file transfer statistics
|
|
1290
|
+
* @return JSON object with transfer statistics
|
|
1291
|
+
*/
|
|
1292
|
+
nlohmann::json get_file_transfer_statistics() const;
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Set file transfer configuration
|
|
1296
|
+
* @param config Transfer configuration settings
|
|
1297
|
+
*/
|
|
1298
|
+
void set_file_transfer_config(const FileTransferConfig& config);
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Get current file transfer configuration
|
|
1302
|
+
* @return Current configuration settings
|
|
1303
|
+
*/
|
|
1304
|
+
const FileTransferConfig& get_file_transfer_config() const;
|
|
1305
|
+
|
|
1306
|
+
// Event Handlers
|
|
1307
|
+
/**
|
|
1308
|
+
* Set file transfer progress callback
|
|
1309
|
+
* @param callback Function to call with progress updates
|
|
1310
|
+
*/
|
|
1311
|
+
void on_file_transfer_progress(FileTransferProgressCallback callback);
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* Set file transfer completion callback
|
|
1315
|
+
* @param callback Function to call when transfers complete
|
|
1316
|
+
*/
|
|
1317
|
+
void on_file_transfer_completed(FileTransferCompletedCallback callback);
|
|
1318
|
+
|
|
1319
|
+
/**
|
|
1320
|
+
* Set incoming file transfer request callback
|
|
1321
|
+
* @param callback Function to call when receiving transfer requests
|
|
1322
|
+
*/
|
|
1323
|
+
void on_file_transfer_request(FileTransferRequestCallback callback);
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Set directory transfer progress callback
|
|
1327
|
+
* @param callback Function to call with directory transfer progress
|
|
1328
|
+
*/
|
|
1329
|
+
void on_directory_transfer_progress(DirectoryTransferProgressCallback callback);
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* Set file request callback (called when receiving file requests)
|
|
1333
|
+
* @param callback Function to call when receiving file requests
|
|
1334
|
+
*/
|
|
1335
|
+
void on_file_request(FileRequestCallback callback);
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* Set directory request callback (called when receiving directory requests)
|
|
1339
|
+
* @param callback Function to call when receiving directory requests
|
|
1340
|
+
*/
|
|
1341
|
+
void on_directory_request(DirectoryRequestCallback callback);
|
|
1342
|
+
|
|
1343
|
+
#ifdef RATS_SEARCH_FEATURES
|
|
1344
|
+
// =========================================================================
|
|
1345
|
+
// BitTorrent API (requires RATS_SEARCH_FEATURES)
|
|
1346
|
+
// =========================================================================
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* Enable BitTorrent functionality
|
|
1350
|
+
* @param listen_port Port to listen for BitTorrent connections (default: 6881)
|
|
1351
|
+
* @return true if BitTorrent was successfully enabled
|
|
1352
|
+
*/
|
|
1353
|
+
bool enable_bittorrent(int listen_port = 6881);
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* Disable BitTorrent functionality
|
|
1357
|
+
*/
|
|
1358
|
+
void disable_bittorrent();
|
|
1359
|
+
|
|
1360
|
+
/**
|
|
1361
|
+
* Check if BitTorrent is enabled
|
|
1362
|
+
* @return true if BitTorrent is active
|
|
1363
|
+
*/
|
|
1364
|
+
bool is_bittorrent_enabled() const;
|
|
1365
|
+
|
|
1366
|
+
/**
|
|
1367
|
+
* Add a torrent from a file
|
|
1368
|
+
* @param torrent_file Path to the .torrent file
|
|
1369
|
+
* @param download_path Directory where files will be downloaded
|
|
1370
|
+
* @return Shared pointer to TorrentDownload object, or nullptr on failure
|
|
1371
|
+
*/
|
|
1372
|
+
std::shared_ptr<TorrentDownload> add_torrent(const std::string& torrent_file,
|
|
1373
|
+
const std::string& download_path);
|
|
1374
|
+
|
|
1375
|
+
/**
|
|
1376
|
+
* Add a torrent from TorrentInfo
|
|
1377
|
+
* @param torrent_info TorrentInfo object with torrent metadata
|
|
1378
|
+
* @param download_path Directory where files will be downloaded
|
|
1379
|
+
* @return Shared pointer to TorrentDownload object, or nullptr on failure
|
|
1380
|
+
*/
|
|
1381
|
+
std::shared_ptr<TorrentDownload> add_torrent(const TorrentInfo& torrent_info,
|
|
1382
|
+
const std::string& download_path);
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* Add a torrent by info hash (magnet link style - uses DHT to find peers)
|
|
1386
|
+
* @param info_hash Info hash of the torrent
|
|
1387
|
+
* @param download_path Directory where files will be downloaded
|
|
1388
|
+
* @return Shared pointer to TorrentDownload object, or nullptr on failure
|
|
1389
|
+
* @note Requires DHT to be running. Will discover peers via DHT.
|
|
1390
|
+
*/
|
|
1391
|
+
std::shared_ptr<TorrentDownload> add_torrent_by_hash(const InfoHash& info_hash,
|
|
1392
|
+
const std::string& download_path);
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Add a torrent by info hash hex string (magnet link style - uses DHT to find peers)
|
|
1396
|
+
* @param info_hash_hex Info hash as 40-character hex string
|
|
1397
|
+
* @param download_path Directory where files will be downloaded
|
|
1398
|
+
* @return Shared pointer to TorrentDownload object, or nullptr on failure
|
|
1399
|
+
* @note Requires DHT to be running. Will discover peers via DHT.
|
|
1400
|
+
*/
|
|
1401
|
+
std::shared_ptr<TorrentDownload> add_torrent_by_hash(const std::string& info_hash_hex,
|
|
1402
|
+
const std::string& download_path);
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* Remove a torrent by info hash
|
|
1406
|
+
* @param info_hash Info hash of the torrent to remove
|
|
1407
|
+
* @return true if torrent was removed successfully
|
|
1408
|
+
*/
|
|
1409
|
+
bool remove_torrent(const InfoHash& info_hash);
|
|
1410
|
+
|
|
1411
|
+
/**
|
|
1412
|
+
* Get a torrent by info hash
|
|
1413
|
+
* @param info_hash Info hash of the torrent
|
|
1414
|
+
* @return Shared pointer to TorrentDownload object, or nullptr if not found
|
|
1415
|
+
*/
|
|
1416
|
+
std::shared_ptr<TorrentDownload> get_torrent(const InfoHash& info_hash);
|
|
1417
|
+
|
|
1418
|
+
/**
|
|
1419
|
+
* Get all active torrents
|
|
1420
|
+
* @return Vector of all active torrent downloads
|
|
1421
|
+
*/
|
|
1422
|
+
std::vector<std::shared_ptr<TorrentDownload>> get_all_torrents();
|
|
1423
|
+
|
|
1424
|
+
/**
|
|
1425
|
+
* Get the number of active torrents
|
|
1426
|
+
* @return Number of active torrents
|
|
1427
|
+
*/
|
|
1428
|
+
size_t get_active_torrents_count() const;
|
|
1429
|
+
|
|
1430
|
+
/**
|
|
1431
|
+
* Get BitTorrent statistics (downloaded and uploaded bytes)
|
|
1432
|
+
* @return Pair of (downloaded_bytes, uploaded_bytes)
|
|
1433
|
+
*/
|
|
1434
|
+
std::pair<uint64_t, uint64_t> get_bittorrent_stats() const;
|
|
1435
|
+
|
|
1436
|
+
/**
|
|
1437
|
+
* Get torrent metadata without downloading (requires DHT to be running)
|
|
1438
|
+
* @param info_hash Info hash of the torrent
|
|
1439
|
+
* @param callback Function called when metadata is retrieved (torrent_info, success, error_message)
|
|
1440
|
+
* @note This only retrieves metadata via BEP 9, it does not start downloading
|
|
1441
|
+
*/
|
|
1442
|
+
void get_torrent_metadata(const InfoHash& info_hash,
|
|
1443
|
+
std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
|
|
1444
|
+
|
|
1445
|
+
/**
|
|
1446
|
+
* Get torrent metadata without downloading by hex string (requires DHT to be running)
|
|
1447
|
+
* @param info_hash_hex Info hash as 40-character hex string
|
|
1448
|
+
* @param callback Function called when metadata is retrieved (torrent_info, success, error_message)
|
|
1449
|
+
* @note This only retrieves metadata via BEP 9, it does not start downloading
|
|
1450
|
+
*/
|
|
1451
|
+
void get_torrent_metadata(const std::string& info_hash_hex,
|
|
1452
|
+
std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
|
|
1453
|
+
#endif // RATS_SEARCH_FEATURES
|
|
1454
|
+
|
|
1455
|
+
private:
|
|
1456
|
+
int listen_port_;
|
|
1457
|
+
std::string bind_address_;
|
|
1458
|
+
int max_peers_;
|
|
1459
|
+
socket_t server_socket_;
|
|
1460
|
+
std::atomic<bool> running_;
|
|
1461
|
+
|
|
1462
|
+
// NAT traversal configuration
|
|
1463
|
+
NatTraversalConfig nat_config_;
|
|
1464
|
+
|
|
1465
|
+
// =========================================================================
|
|
1466
|
+
// MUTEX LOCKING ORDER - CRITICAL FOR DEADLOCK PREVENTION
|
|
1467
|
+
// =========================================================================
|
|
1468
|
+
// When acquiring multiple mutexes, ALWAYS follow this strict order:
|
|
1469
|
+
//
|
|
1470
|
+
// 1. config_mutex_ (Configuration and peer ID)
|
|
1471
|
+
// 2. protocol_config_mutex_ (Protocol name and version)
|
|
1472
|
+
// 3. encryption_mutex_ (Encryption settings and keys)
|
|
1473
|
+
// 4. nat_mutex_ (NAT detection and characteristics)
|
|
1474
|
+
// 5. public_ip_mutex_ (Public IP address)
|
|
1475
|
+
// 6. local_addresses_mutex_ (Local interface addresses)
|
|
1476
|
+
// 7. ice_coordination_mutex_ (ICE coordination tracking)
|
|
1477
|
+
// 8. connection_attempts_mutex_ (Connection attempt history)
|
|
1478
|
+
// 9. peers_mutex_ (Peer management - most frequently locked)
|
|
1479
|
+
// 10. socket_send_mutexes_mutex_ (Socket send mutex management)
|
|
1480
|
+
// 11. message_handlers_mutex_ (Message handler registration)
|
|
1481
|
+
// =========================================================================
|
|
1482
|
+
|
|
1483
|
+
// Configuration persistence
|
|
1484
|
+
std::string our_peer_id_; // Our persistent peer ID
|
|
1485
|
+
std::string data_directory_; // Directory where data files are stored
|
|
1486
|
+
mutable std::mutex config_mutex_; // [1] Protects configuration data
|
|
1487
|
+
static const std::string CONFIG_FILE_NAME; // "config.json"
|
|
1488
|
+
static const std::string PEERS_FILE_NAME; // "peers.rats"
|
|
1489
|
+
static const std::string PEERS_EVER_FILE_NAME; // "peers_ever.rats"
|
|
1490
|
+
|
|
1491
|
+
// Encryption state
|
|
1492
|
+
NoiseKey static_encryption_key_; // Our static encryption key
|
|
1493
|
+
bool encryption_enabled_; // Whether encryption is enabled
|
|
1494
|
+
mutable std::mutex encryption_mutex_; // [3] Protects encryption state
|
|
1495
|
+
|
|
1496
|
+
// ICE and NAT traversal
|
|
1497
|
+
std::unique_ptr<IceAgent> ice_agent_; // ICE agent for NAT traversal
|
|
1498
|
+
std::unique_ptr<AdvancedNatDetector> nat_detector_; // Advanced NAT type detection
|
|
1499
|
+
NatType detected_nat_type_; // Our detected NAT type
|
|
1500
|
+
NatTypeInfo nat_characteristics_; // Detailed NAT information
|
|
1501
|
+
mutable std::mutex nat_mutex_; // [4] Protects NAT-related data
|
|
1502
|
+
|
|
1503
|
+
// ICE coordination tracking to prevent duplicate attempts
|
|
1504
|
+
std::unordered_set<std::string> ice_coordination_in_progress_; // Set of peer_ids having ICE coordination
|
|
1505
|
+
mutable std::mutex ice_coordination_mutex_; // [7] Protects ICE coordination state
|
|
1506
|
+
|
|
1507
|
+
// Connection attempt tracking
|
|
1508
|
+
std::unordered_map<std::string, std::vector<ConnectionAttemptResult>> connection_attempts_;
|
|
1509
|
+
mutable std::mutex connection_attempts_mutex_; // [8] Protects connection attempts
|
|
1510
|
+
|
|
1511
|
+
// Organized peer management using RatsPeer struct
|
|
1512
|
+
mutable std::mutex peers_mutex_; // [9] Protects peer data (most frequently locked)
|
|
1513
|
+
std::unordered_map<std::string, RatsPeer> peers_; // keyed by peer_id
|
|
1514
|
+
std::unordered_map<socket_t, std::string> socket_to_peer_id_; // for quick socket->peer_id lookup
|
|
1515
|
+
std::unordered_map<std::string, std::string> address_to_peer_id_; // for duplicate detection (normalized_address->peer_id)
|
|
1516
|
+
|
|
1517
|
+
// Per-socket synchronization for thread-safe message sending
|
|
1518
|
+
mutable std::mutex socket_send_mutexes_mutex_; // [10] Protects socket send mutex map
|
|
1519
|
+
std::unordered_map<socket_t, std::shared_ptr<std::mutex>> socket_send_mutexes_;
|
|
1520
|
+
|
|
1521
|
+
// Server and client management
|
|
1522
|
+
std::thread server_thread_;
|
|
1523
|
+
std::thread management_thread_;
|
|
1524
|
+
|
|
1525
|
+
ConnectionCallback connection_callback_;
|
|
1526
|
+
AdvancedConnectionCallback advanced_connection_callback_;
|
|
1527
|
+
BinaryDataCallback binary_data_callback_;
|
|
1528
|
+
StringDataCallback string_data_callback_;
|
|
1529
|
+
JsonDataCallback json_data_callback_;
|
|
1530
|
+
DisconnectCallback disconnect_callback_;
|
|
1531
|
+
NatTraversalProgressCallback nat_progress_callback_;
|
|
1532
|
+
IceCandidateDiscoveredCallback ice_candidate_callback_;
|
|
1533
|
+
|
|
1534
|
+
// DHT client for peer discovery
|
|
1535
|
+
std::unique_ptr<DhtClient> dht_client_;
|
|
1536
|
+
|
|
1537
|
+
// STUN client for public IP discovery
|
|
1538
|
+
std::unique_ptr<StunClient> stun_client_;
|
|
1539
|
+
std::string public_ip_;
|
|
1540
|
+
mutable std::mutex public_ip_mutex_; // [5] Protects public IP address
|
|
1541
|
+
|
|
1542
|
+
// mDNS client for local network discovery
|
|
1543
|
+
std::unique_ptr<MdnsClient> mdns_client_;
|
|
1544
|
+
std::function<void(const std::string&, int, const std::string&)> mdns_callback_;
|
|
1545
|
+
|
|
1546
|
+
// GossipSub for publish-subscribe messaging
|
|
1547
|
+
std::unique_ptr<GossipSub> gossipsub_;
|
|
1548
|
+
|
|
1549
|
+
// File transfer manager
|
|
1550
|
+
std::unique_ptr<FileTransferManager> file_transfer_manager_;
|
|
1551
|
+
|
|
1552
|
+
#ifdef RATS_SEARCH_FEATURES
|
|
1553
|
+
// BitTorrent client (optional, requires RATS_SEARCH_FEATURES)
|
|
1554
|
+
std::unique_ptr<BitTorrentClient> bittorrent_client_;
|
|
1555
|
+
#endif
|
|
1556
|
+
|
|
1557
|
+
void initialize_modules();
|
|
1558
|
+
void destroy_modules();
|
|
1559
|
+
|
|
1560
|
+
void server_loop();
|
|
1561
|
+
void management_loop();
|
|
1562
|
+
void handle_client(socket_t client_socket, const std::string& peer_hash_id);
|
|
1563
|
+
void remove_peer(socket_t socket);
|
|
1564
|
+
std::string generate_peer_hash_id(socket_t socket, const std::string& connection_info);
|
|
1565
|
+
void handle_dht_peer_discovery(const std::vector<Peer>& peers, const InfoHash& info_hash);
|
|
1566
|
+
void handle_mdns_service_discovery(const MdnsService& service, bool is_new);
|
|
1567
|
+
|
|
1568
|
+
// Message header helpers
|
|
1569
|
+
std::vector<uint8_t> create_message_with_header(const std::vector<uint8_t>& payload, MessageDataType type);
|
|
1570
|
+
bool parse_message_with_header(const std::vector<uint8_t>& message, MessageHeader& header, std::vector<uint8_t>& payload) const;
|
|
1571
|
+
|
|
1572
|
+
// Enhanced connection establishment
|
|
1573
|
+
bool attempt_direct_connection(const std::string& host, int port, ConnectionAttemptResult& result);
|
|
1574
|
+
bool attempt_stun_assisted_connection(const std::string& host, int port, ConnectionAttemptResult& result);
|
|
1575
|
+
bool attempt_ice_connection(const std::string& host, int port, ConnectionAttemptResult& result);
|
|
1576
|
+
bool attempt_turn_relay_connection(const std::string& host, int port, ConnectionAttemptResult& result);
|
|
1577
|
+
bool attempt_hole_punch_connection(const std::string& host, int port, ConnectionAttemptResult& result);
|
|
1578
|
+
|
|
1579
|
+
// ICE coordination helpers
|
|
1580
|
+
void handle_ice_candidate_discovered(const std::string& peer_id, const IceCandidate& candidate);
|
|
1581
|
+
void handle_ice_connection_state_change(const std::string& peer_id, IceConnectionState state);
|
|
1582
|
+
void initiate_ice_with_peer(const std::string& peer_id, const std::string& host, int port);
|
|
1583
|
+
|
|
1584
|
+
// NAT traversal message handlers
|
|
1585
|
+
void handle_ice_offer_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1586
|
+
void handle_ice_answer_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1587
|
+
void handle_ice_candidate_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1588
|
+
void handle_hole_punch_coordination_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1589
|
+
void handle_nat_info_exchange_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1590
|
+
void send_nat_info_to_peer(socket_t socket, const std::string& peer_id);
|
|
1591
|
+
|
|
1592
|
+
// New peer management methods using RatsPeer
|
|
1593
|
+
void add_peer(const RatsPeer& peer);
|
|
1594
|
+
void add_peer_unlocked(const RatsPeer& peer); // Assumes peers_mutex_ is already locked
|
|
1595
|
+
void remove_peer_by_id(const std::string& peer_id);
|
|
1596
|
+
void remove_peer_by_id_unlocked(const std::string& peer_id); // Assumes peers_mutex_ is already locked
|
|
1597
|
+
bool is_already_connected_to_address(const std::string& normalized_address) const;
|
|
1598
|
+
std::string normalize_peer_address(const std::string& ip, int port) const;
|
|
1599
|
+
|
|
1600
|
+
// Local interface address blocking (ignore list)
|
|
1601
|
+
std::vector<std::string> local_interface_addresses_;
|
|
1602
|
+
mutable std::mutex local_addresses_mutex_; // [6] Protects local interface addresses
|
|
1603
|
+
void initialize_local_addresses();
|
|
1604
|
+
void refresh_local_addresses();
|
|
1605
|
+
bool is_blocked_address(const std::string& ip_address) const;
|
|
1606
|
+
bool should_ignore_peer(const std::string& ip, int port) const;
|
|
1607
|
+
static bool parse_address_string(const std::string& address_str, std::string& out_ip, int& out_port);
|
|
1608
|
+
|
|
1609
|
+
// Helper functions that assume mutex is already locked
|
|
1610
|
+
int get_peer_count_unlocked() const; // Helper that assumes peers_mutex_ is already locked
|
|
1611
|
+
|
|
1612
|
+
// Handshake protocol
|
|
1613
|
+
static constexpr const char* RATS_PROTOCOL_VERSION = "1.0";
|
|
1614
|
+
static constexpr int HANDSHAKE_TIMEOUT_SECONDS = 10;
|
|
1615
|
+
|
|
1616
|
+
// Custom protocol configuration
|
|
1617
|
+
std::string custom_protocol_name_; // Custom protocol name (default: "rats")
|
|
1618
|
+
std::string custom_protocol_version_; // Custom protocol version (default: "1.0")
|
|
1619
|
+
mutable std::mutex protocol_config_mutex_; // [2] Protects protocol configuration
|
|
1620
|
+
|
|
1621
|
+
struct HandshakeMessage {
|
|
1622
|
+
std::string protocol;
|
|
1623
|
+
std::string version;
|
|
1624
|
+
std::string peer_id;
|
|
1625
|
+
std::string message_type;
|
|
1626
|
+
int64_t timestamp;
|
|
1627
|
+
};
|
|
1628
|
+
|
|
1629
|
+
std::string create_handshake_message(const std::string& message_type, const std::string& our_peer_id) const;
|
|
1630
|
+
bool parse_handshake_message(const std::string& message, HandshakeMessage& out_msg) const;
|
|
1631
|
+
bool validate_handshake_message(const HandshakeMessage& msg) const;
|
|
1632
|
+
bool is_handshake_message(const std::string& message) const;
|
|
1633
|
+
bool send_handshake(socket_t socket, const std::string& our_peer_id);
|
|
1634
|
+
bool send_handshake_unlocked(socket_t socket, const std::string& our_peer_id);
|
|
1635
|
+
bool handle_handshake_message(socket_t socket, const std::string& peer_hash_id, const std::string& message);
|
|
1636
|
+
void check_handshake_timeouts();
|
|
1637
|
+
void log_handshake_completion(const RatsPeer& peer);
|
|
1638
|
+
void log_handshake_completion_unlocked(const RatsPeer& peer);
|
|
1639
|
+
|
|
1640
|
+
// Automatic discovery
|
|
1641
|
+
std::atomic<bool> auto_discovery_running_;
|
|
1642
|
+
std::thread auto_discovery_thread_;
|
|
1643
|
+
void automatic_discovery_loop();
|
|
1644
|
+
void announce_rats_peer();
|
|
1645
|
+
void search_rats_peers();
|
|
1646
|
+
|
|
1647
|
+
// Message handling system
|
|
1648
|
+
nlohmann::json create_rats_message(const std::string& type, const nlohmann::json& payload, const std::string& sender_peer_id);
|
|
1649
|
+
void handle_rats_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& message);
|
|
1650
|
+
|
|
1651
|
+
// Specific message handlers
|
|
1652
|
+
void handle_peer_exchange_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1653
|
+
void handle_peers_request_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1654
|
+
void handle_peers_response_message(socket_t socket, const std::string& peer_hash_id, const nlohmann::json& payload);
|
|
1655
|
+
|
|
1656
|
+
// Message creation and broadcasting
|
|
1657
|
+
nlohmann::json create_peer_exchange_message(const RatsPeer& peer);
|
|
1658
|
+
void broadcast_peer_exchange_message(const RatsPeer& new_peer);
|
|
1659
|
+
nlohmann::json create_peers_request_message(const std::string& sender_peer_id);
|
|
1660
|
+
nlohmann::json create_peers_response_message(const std::vector<RatsPeer>& peers, const std::string& sender_peer_id);
|
|
1661
|
+
std::vector<RatsPeer> get_random_peers(int max_count, const std::string& exclude_peer_id = "") const;
|
|
1662
|
+
void send_peers_request(socket_t socket, const std::string& our_peer_id);
|
|
1663
|
+
|
|
1664
|
+
int broadcast_rats_message(const nlohmann::json& message, const std::string& exclude_peer_id = "");
|
|
1665
|
+
int broadcast_rats_message_to_validated_peers(const nlohmann::json& message, const std::string& exclude_peer_id = "");
|
|
1666
|
+
// Message exchange API implementation
|
|
1667
|
+
struct MessageHandler {
|
|
1668
|
+
MessageCallback callback;
|
|
1669
|
+
bool is_once;
|
|
1670
|
+
|
|
1671
|
+
MessageHandler(MessageCallback cb, bool once) : callback(cb), is_once(once) {}
|
|
1672
|
+
};
|
|
1673
|
+
|
|
1674
|
+
std::unordered_map<std::string, std::vector<MessageHandler>> message_handlers_;
|
|
1675
|
+
mutable std::mutex message_handlers_mutex_; // [11] Protects message handlers
|
|
1676
|
+
|
|
1677
|
+
void call_message_handlers(const std::string& message_type, const std::string& peer_id, const nlohmann::json& data);
|
|
1678
|
+
void call_callback_safely(const MessageCallback& callback, const std::string& peer_id, const nlohmann::json& data);
|
|
1679
|
+
void remove_once_handlers(const std::string& message_type);
|
|
1680
|
+
|
|
1681
|
+
// Per-socket synchronization helpers
|
|
1682
|
+
std::shared_ptr<std::mutex> get_socket_send_mutex(socket_t socket);
|
|
1683
|
+
void cleanup_socket_send_mutex(socket_t socket);
|
|
1684
|
+
|
|
1685
|
+
// Configuration persistence helpers
|
|
1686
|
+
std::string generate_persistent_peer_id() const;
|
|
1687
|
+
nlohmann::json serialize_peer_for_persistence(const RatsPeer& peer) const;
|
|
1688
|
+
bool deserialize_peer_from_persistence(const nlohmann::json& json, std::string& ip, int& port, std::string& peer_id) const;
|
|
1689
|
+
std::string get_config_file_path() const;
|
|
1690
|
+
std::string get_peers_file_path() const;
|
|
1691
|
+
std::string get_peers_ever_file_path() const;
|
|
1692
|
+
bool save_peers_to_file();
|
|
1693
|
+
bool append_peer_to_historical_file(const RatsPeer& peer);
|
|
1694
|
+
int load_and_reconnect_historical_peers();
|
|
1695
|
+
|
|
1696
|
+
// NAT traversal helpers
|
|
1697
|
+
void initialize_nat_traversal();
|
|
1698
|
+
void detect_and_cache_nat_type();
|
|
1699
|
+
void update_connection_statistics(const std::string& peer_id, const ConnectionAttemptResult& result);
|
|
1700
|
+
std::string select_best_connection_strategy(const std::string& host, int port);
|
|
1701
|
+
NatType map_characteristics_to_nat_type(const NatTypeInfo& characteristics);
|
|
1702
|
+
void log_nat_detection_results();
|
|
1703
|
+
bool perform_tcp_connection(const std::string& host, int port, ConnectionAttemptResult& result);
|
|
1704
|
+
|
|
1705
|
+
// ICE coordination helpers
|
|
1706
|
+
void initialize_ice_agent();
|
|
1707
|
+
void setup_ice_callbacks();
|
|
1708
|
+
void update_peer_ice_info(socket_t socket, const nlohmann::json& payload);
|
|
1709
|
+
void add_candidate_to_peer(socket_t socket, const IceCandidate& candidate);
|
|
1710
|
+
bool should_initiate_ice_coordination(const std::string& peer_id);
|
|
1711
|
+
void mark_ice_coordination_in_progress(const std::string& peer_id);
|
|
1712
|
+
void remove_ice_coordination_tracking(const std::string& peer_id);
|
|
1713
|
+
void cleanup_ice_coordination_for_peer(const std::string& peer_id);
|
|
1714
|
+
nlohmann::json get_ice_statistics() const;
|
|
1715
|
+
bool is_ice_enabled() const;
|
|
1716
|
+
bool is_peer_ice_connected(const std::string& peer_id) const;
|
|
1717
|
+
void cleanup_ice_resources();
|
|
1718
|
+
};
|
|
1719
|
+
|
|
1720
|
+
// Utility functions
|
|
1721
|
+
std::unique_ptr<RatsClient> create_rats_client(int listen_port);
|
|
1722
|
+
|
|
1723
|
+
// Library version query (stable, binding-friendly)
|
|
1724
|
+
RATS_API const char* rats_get_library_version_string();
|
|
1725
|
+
RATS_API void rats_get_library_version(int* major, int* minor, int* patch, int* build);
|
|
1726
|
+
RATS_API const char* rats_get_library_git_describe();
|
|
1727
|
+
RATS_API uint32_t rats_get_library_abi(); // packed as (major<<16)|(minor<<8)|patch
|
|
1728
|
+
|
|
1729
|
+
} // namespace librats
|