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,403 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <unordered_map>
|
|
6
|
+
#include <unordered_set>
|
|
7
|
+
#include <chrono>
|
|
8
|
+
#include <memory>
|
|
9
|
+
#include <functional>
|
|
10
|
+
#include <mutex>
|
|
11
|
+
#include <atomic>
|
|
12
|
+
#include <thread>
|
|
13
|
+
#include <condition_variable>
|
|
14
|
+
#include <random>
|
|
15
|
+
#include "json.hpp"
|
|
16
|
+
|
|
17
|
+
namespace librats {
|
|
18
|
+
|
|
19
|
+
// Forward declarations
|
|
20
|
+
class RatsClient;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* GossipSub message types
|
|
24
|
+
*/
|
|
25
|
+
enum class GossipSubMessageType {
|
|
26
|
+
SUBSCRIBE, // Subscribe to a topic
|
|
27
|
+
UNSUBSCRIBE, // Unsubscribe from a topic
|
|
28
|
+
PUBLISH, // Publish a message to a topic
|
|
29
|
+
GOSSIP, // Gossip message about published content
|
|
30
|
+
GRAFT, // Join mesh for a topic
|
|
31
|
+
PRUNE, // Leave mesh for a topic
|
|
32
|
+
IHAVE, // Announce having certain messages
|
|
33
|
+
IWANT, // Request specific messages
|
|
34
|
+
HEARTBEAT // Periodic heartbeat with control information
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Message metadata for tracking and deduplication
|
|
39
|
+
*/
|
|
40
|
+
struct MessageMetadata {
|
|
41
|
+
std::string message_id;
|
|
42
|
+
std::string topic;
|
|
43
|
+
std::string sender_peer_id;
|
|
44
|
+
std::chrono::steady_clock::time_point first_seen;
|
|
45
|
+
std::chrono::steady_clock::time_point last_seen;
|
|
46
|
+
std::vector<std::string> seen_from_peers;
|
|
47
|
+
int hop_count;
|
|
48
|
+
bool validated;
|
|
49
|
+
|
|
50
|
+
MessageMetadata(const std::string& id, const std::string& t, const std::string& sender)
|
|
51
|
+
: message_id(id), topic(t), sender_peer_id(sender),
|
|
52
|
+
first_seen(std::chrono::steady_clock::now()),
|
|
53
|
+
last_seen(std::chrono::steady_clock::now()),
|
|
54
|
+
hop_count(0), validated(false) {}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Peer scoring metrics for mesh management
|
|
59
|
+
*/
|
|
60
|
+
struct PeerScore {
|
|
61
|
+
std::string peer_id;
|
|
62
|
+
double score;
|
|
63
|
+
|
|
64
|
+
// Score components
|
|
65
|
+
double topic_score; // Score based on topic participation
|
|
66
|
+
double delivery_score; // Score based on message delivery
|
|
67
|
+
double mesh_behavior_score; // Score based on mesh behavior
|
|
68
|
+
double invalid_message_score; // Penalty for invalid messages
|
|
69
|
+
|
|
70
|
+
// Timing metrics
|
|
71
|
+
std::chrono::steady_clock::time_point last_updated;
|
|
72
|
+
std::chrono::steady_clock::time_point connected_since;
|
|
73
|
+
|
|
74
|
+
// Behavioral metrics
|
|
75
|
+
int messages_delivered;
|
|
76
|
+
int messages_invalid;
|
|
77
|
+
int graft_requests;
|
|
78
|
+
int prune_requests;
|
|
79
|
+
|
|
80
|
+
PeerScore(const std::string& id)
|
|
81
|
+
: peer_id(id), score(0.0), topic_score(0.0), delivery_score(0.0),
|
|
82
|
+
mesh_behavior_score(0.0), invalid_message_score(0.0),
|
|
83
|
+
last_updated(std::chrono::steady_clock::now()),
|
|
84
|
+
connected_since(std::chrono::steady_clock::now()),
|
|
85
|
+
messages_delivered(0), messages_invalid(0),
|
|
86
|
+
graft_requests(0), prune_requests(0) {}
|
|
87
|
+
|
|
88
|
+
void update_score();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Topic subscription information
|
|
93
|
+
*/
|
|
94
|
+
struct TopicSubscription {
|
|
95
|
+
std::string topic;
|
|
96
|
+
std::unordered_set<std::string> subscribers; // All peers subscribed to this topic
|
|
97
|
+
std::unordered_set<std::string> mesh_peers; // Peers in our mesh for this topic
|
|
98
|
+
std::unordered_set<std::string> fanout_peers; // Peers in fanout (when we're not subscribed)
|
|
99
|
+
std::chrono::steady_clock::time_point last_fanout_prune;
|
|
100
|
+
|
|
101
|
+
TopicSubscription(const std::string& t) : topic(t), last_fanout_prune(std::chrono::steady_clock::now()) {}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* GossipSub configuration parameters
|
|
106
|
+
*/
|
|
107
|
+
struct GossipSubConfig {
|
|
108
|
+
// Mesh parameters
|
|
109
|
+
int mesh_low; // Minimum number of peers in mesh
|
|
110
|
+
int mesh_high; // Maximum number of peers in mesh
|
|
111
|
+
int mesh_optimal; // Optimal number of peers in mesh
|
|
112
|
+
|
|
113
|
+
// Fanout parameters
|
|
114
|
+
int fanout_size; // Number of peers for fanout
|
|
115
|
+
std::chrono::milliseconds fanout_ttl; // Time to live for fanout
|
|
116
|
+
|
|
117
|
+
// Gossip parameters
|
|
118
|
+
int gossip_factor; // Number of peers to gossip to
|
|
119
|
+
int gossip_lazy; // Lazy pull parameter
|
|
120
|
+
std::chrono::milliseconds gossip_retransmit; // Gossip retransmission interval
|
|
121
|
+
|
|
122
|
+
// Heartbeat parameters
|
|
123
|
+
std::chrono::milliseconds heartbeat_interval; // Heartbeat interval
|
|
124
|
+
|
|
125
|
+
// Message parameters
|
|
126
|
+
std::chrono::milliseconds message_cache_ttl; // Message cache time to live
|
|
127
|
+
int max_ihave_messages; // Maximum messages in IHAVE
|
|
128
|
+
int max_iwant_messages; // Maximum messages in IWANT
|
|
129
|
+
|
|
130
|
+
// Scoring parameters
|
|
131
|
+
double score_threshold_accept; // Minimum score to accept messages
|
|
132
|
+
double score_threshold_gossip; // Minimum score to gossip to peer
|
|
133
|
+
double score_threshold_mesh; // Minimum score to keep in mesh
|
|
134
|
+
double score_threshold_publish; // Minimum score to accept published messages
|
|
135
|
+
|
|
136
|
+
GossipSubConfig()
|
|
137
|
+
: mesh_low(4), mesh_high(12), mesh_optimal(6),
|
|
138
|
+
fanout_size(6), fanout_ttl(std::chrono::seconds(60)),
|
|
139
|
+
gossip_factor(3), gossip_lazy(3), gossip_retransmit(std::chrono::seconds(3)),
|
|
140
|
+
heartbeat_interval(std::chrono::seconds(1)),
|
|
141
|
+
message_cache_ttl(std::chrono::minutes(5)),
|
|
142
|
+
max_ihave_messages(5000), max_iwant_messages(5000),
|
|
143
|
+
score_threshold_accept(-100.0), score_threshold_gossip(-1000.0),
|
|
144
|
+
score_threshold_mesh(-10.0), score_threshold_publish(-50.0) {}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Message validation result
|
|
149
|
+
*/
|
|
150
|
+
enum class ValidationResult {
|
|
151
|
+
ACCEPT,
|
|
152
|
+
REJECT,
|
|
153
|
+
IGNORE_MSG
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Callback types for GossipSub
|
|
158
|
+
*/
|
|
159
|
+
using MessageValidator = std::function<ValidationResult(const std::string& topic, const std::string& message, const std::string& sender_peer_id)>;
|
|
160
|
+
using MessageHandler = std::function<void(const std::string& topic, const std::string& message, const std::string& sender_peer_id)>;
|
|
161
|
+
using PeerJoinedHandler = std::function<void(const std::string& topic, const std::string& peer_id)>;
|
|
162
|
+
using PeerLeftHandler = std::function<void(const std::string& topic, const std::string& peer_id)>;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Main GossipSub implementation class
|
|
166
|
+
*/
|
|
167
|
+
class GossipSub {
|
|
168
|
+
friend class RatsClient;
|
|
169
|
+
|
|
170
|
+
public:
|
|
171
|
+
/**
|
|
172
|
+
* Constructor
|
|
173
|
+
* @param rats_client Reference to the RatsClient instance
|
|
174
|
+
* @param config GossipSub configuration
|
|
175
|
+
*/
|
|
176
|
+
explicit GossipSub(RatsClient& rats_client, const GossipSubConfig& config = GossipSubConfig());
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Destructor
|
|
180
|
+
*/
|
|
181
|
+
~GossipSub();
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Start the GossipSub service
|
|
185
|
+
* @return true if started successfully
|
|
186
|
+
*/
|
|
187
|
+
bool start();
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Stop the GossipSub service
|
|
191
|
+
*/
|
|
192
|
+
void stop();
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check if GossipSub is running
|
|
196
|
+
* @return true if running
|
|
197
|
+
*/
|
|
198
|
+
bool is_running() const;
|
|
199
|
+
|
|
200
|
+
// Topic management
|
|
201
|
+
/**
|
|
202
|
+
* Subscribe to a topic
|
|
203
|
+
* @param topic Topic name to subscribe to
|
|
204
|
+
* @return true if subscription successful
|
|
205
|
+
*/
|
|
206
|
+
bool subscribe(const std::string& topic);
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Unsubscribe from a topic
|
|
210
|
+
* @param topic Topic name to unsubscribe from
|
|
211
|
+
* @return true if unsubscription successful
|
|
212
|
+
*/
|
|
213
|
+
bool unsubscribe(const std::string& topic);
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Check if subscribed to a topic
|
|
217
|
+
* @param topic Topic name to check
|
|
218
|
+
* @return true if subscribed
|
|
219
|
+
*/
|
|
220
|
+
bool is_subscribed(const std::string& topic) const;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Get list of subscribed topics
|
|
224
|
+
* @return Vector of topic names
|
|
225
|
+
*/
|
|
226
|
+
std::vector<std::string> get_subscribed_topics() const;
|
|
227
|
+
|
|
228
|
+
// Message publishing
|
|
229
|
+
/**
|
|
230
|
+
* Publish a message to a topic
|
|
231
|
+
* @param topic Topic to publish to
|
|
232
|
+
* @param message Message content
|
|
233
|
+
* @return true if published successfully
|
|
234
|
+
*/
|
|
235
|
+
bool publish(const std::string& topic, const std::string& message);
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Publish a JSON message to a topic
|
|
239
|
+
* @param topic Topic to publish to
|
|
240
|
+
* @param message JSON message content
|
|
241
|
+
* @return true if published successfully
|
|
242
|
+
*/
|
|
243
|
+
bool publish(const std::string& topic, const nlohmann::json& message);
|
|
244
|
+
|
|
245
|
+
// Callback registration
|
|
246
|
+
/**
|
|
247
|
+
* Set message validator for a topic
|
|
248
|
+
* @param topic Topic name (empty for all topics)
|
|
249
|
+
* @param validator Validation function
|
|
250
|
+
*/
|
|
251
|
+
void set_message_validator(const std::string& topic, MessageValidator validator);
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Set message handler for a topic
|
|
255
|
+
* @param topic Topic name
|
|
256
|
+
* @param handler Message handler function
|
|
257
|
+
*/
|
|
258
|
+
void set_message_handler(const std::string& topic, MessageHandler handler);
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Set peer joined handler for a topic
|
|
262
|
+
* @param topic Topic name
|
|
263
|
+
* @param handler Peer joined handler function
|
|
264
|
+
*/
|
|
265
|
+
void set_peer_joined_handler(const std::string& topic, PeerJoinedHandler handler);
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Set peer left handler for a topic
|
|
269
|
+
* @param topic Topic name
|
|
270
|
+
* @param handler Peer left handler function
|
|
271
|
+
*/
|
|
272
|
+
void set_peer_left_handler(const std::string& topic, PeerLeftHandler handler);
|
|
273
|
+
|
|
274
|
+
// Peer and mesh information
|
|
275
|
+
/**
|
|
276
|
+
* Get peers subscribed to a topic
|
|
277
|
+
* @param topic Topic name
|
|
278
|
+
* @return Vector of peer IDs
|
|
279
|
+
*/
|
|
280
|
+
std::vector<std::string> get_topic_peers(const std::string& topic) const;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Get mesh peers for a topic
|
|
284
|
+
* @param topic Topic name
|
|
285
|
+
* @return Vector of peer IDs in the mesh
|
|
286
|
+
*/
|
|
287
|
+
std::vector<std::string> get_mesh_peers(const std::string& topic) const;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Get peer score
|
|
291
|
+
* @param peer_id Peer ID
|
|
292
|
+
* @return Peer score
|
|
293
|
+
*/
|
|
294
|
+
double get_peer_score(const std::string& peer_id) const;
|
|
295
|
+
|
|
296
|
+
// Statistics and debugging
|
|
297
|
+
/**
|
|
298
|
+
* Get GossipSub statistics
|
|
299
|
+
* @return JSON object with statistics
|
|
300
|
+
*/
|
|
301
|
+
nlohmann::json get_statistics() const;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Get message cache statistics
|
|
305
|
+
* @return JSON object with cache statistics
|
|
306
|
+
*/
|
|
307
|
+
nlohmann::json get_cache_statistics() const;
|
|
308
|
+
|
|
309
|
+
private:
|
|
310
|
+
RatsClient& rats_client_;
|
|
311
|
+
GossipSubConfig config_;
|
|
312
|
+
std::atomic<bool> running_;
|
|
313
|
+
|
|
314
|
+
// Thread management
|
|
315
|
+
std::thread heartbeat_thread_;
|
|
316
|
+
mutable std::mutex heartbeat_mutex_;
|
|
317
|
+
std::condition_variable heartbeat_cv_;
|
|
318
|
+
|
|
319
|
+
// Topic management
|
|
320
|
+
mutable std::mutex topics_mutex_;
|
|
321
|
+
std::unordered_map<std::string, std::unique_ptr<TopicSubscription>> topics_;
|
|
322
|
+
std::unordered_set<std::string> subscribed_topics_;
|
|
323
|
+
|
|
324
|
+
// Peer scoring
|
|
325
|
+
mutable std::mutex scores_mutex_;
|
|
326
|
+
std::unordered_map<std::string, std::unique_ptr<PeerScore>> peer_scores_;
|
|
327
|
+
|
|
328
|
+
// Message cache and deduplication
|
|
329
|
+
mutable std::mutex message_cache_mutex_;
|
|
330
|
+
std::unordered_map<std::string, std::unique_ptr<MessageMetadata>> message_cache_;
|
|
331
|
+
std::unordered_map<std::string, std::chrono::steady_clock::time_point> message_ids_seen_;
|
|
332
|
+
|
|
333
|
+
// Handlers and validators
|
|
334
|
+
mutable std::mutex handlers_mutex_;
|
|
335
|
+
std::unordered_map<std::string, MessageValidator> message_validators_; // topic -> validator
|
|
336
|
+
std::unordered_map<std::string, MessageHandler> message_handlers_; // topic -> handler
|
|
337
|
+
std::unordered_map<std::string, PeerJoinedHandler> peer_joined_handlers_; // topic -> handler
|
|
338
|
+
std::unordered_map<std::string, PeerLeftHandler> peer_left_handlers_; // topic -> handler
|
|
339
|
+
MessageValidator global_validator_; // Global validator for all topics
|
|
340
|
+
|
|
341
|
+
// Control message queues for heartbeat
|
|
342
|
+
mutable std::mutex control_queue_mutex_;
|
|
343
|
+
std::vector<nlohmann::json> pending_grafts_;
|
|
344
|
+
std::vector<nlohmann::json> pending_prunes_;
|
|
345
|
+
std::vector<nlohmann::json> pending_ihaves_;
|
|
346
|
+
std::vector<nlohmann::json> pending_iwants_;
|
|
347
|
+
|
|
348
|
+
// Random number generation
|
|
349
|
+
mutable std::mutex rng_mutex_;
|
|
350
|
+
std::mt19937 rng_;
|
|
351
|
+
|
|
352
|
+
// Internal methods
|
|
353
|
+
void heartbeat_loop();
|
|
354
|
+
void process_heartbeat();
|
|
355
|
+
void handle_gossipsub_message(const std::string& peer_id, const nlohmann::json& message);
|
|
356
|
+
|
|
357
|
+
// Message handling
|
|
358
|
+
void handle_subscribe(const std::string& peer_id, const nlohmann::json& payload);
|
|
359
|
+
void handle_unsubscribe(const std::string& peer_id, const nlohmann::json& payload);
|
|
360
|
+
void handle_publish(const std::string& peer_id, const nlohmann::json& payload);
|
|
361
|
+
void handle_gossip(const std::string& peer_id, const nlohmann::json& payload);
|
|
362
|
+
void handle_graft(const std::string& peer_id, const nlohmann::json& payload);
|
|
363
|
+
void handle_prune(const std::string& peer_id, const nlohmann::json& payload);
|
|
364
|
+
void handle_ihave(const std::string& peer_id, const nlohmann::json& payload);
|
|
365
|
+
void handle_iwant(const std::string& peer_id, const nlohmann::json& payload);
|
|
366
|
+
void handle_heartbeat(const std::string& peer_id, const nlohmann::json& payload);
|
|
367
|
+
|
|
368
|
+
// Mesh management
|
|
369
|
+
void maintain_mesh(const std::string& topic);
|
|
370
|
+
void add_peer_to_mesh(const std::string& topic, const std::string& peer_id);
|
|
371
|
+
void remove_peer_from_mesh(const std::string& topic, const std::string& peer_id);
|
|
372
|
+
std::vector<std::string> select_peers_for_mesh(const std::string& topic, int count);
|
|
373
|
+
std::vector<std::string> select_peers_for_gossip(const std::string& topic, int count, const std::unordered_set<std::string>& exclude = {});
|
|
374
|
+
|
|
375
|
+
// Message utilities
|
|
376
|
+
std::string generate_message_id(const std::string& topic, const std::string& message, const std::string& sender_peer_id);
|
|
377
|
+
bool is_message_seen(const std::string& message_id);
|
|
378
|
+
void cache_message(const std::string& message_id, const std::string& topic, const std::string& message, const std::string& sender_peer_id);
|
|
379
|
+
void cleanup_message_cache();
|
|
380
|
+
|
|
381
|
+
// Peer management
|
|
382
|
+
void update_peer_score(const std::string& peer_id);
|
|
383
|
+
void handle_peer_connected(const std::string& peer_id);
|
|
384
|
+
void handle_peer_disconnected(const std::string& peer_id);
|
|
385
|
+
|
|
386
|
+
// Message sending utilities
|
|
387
|
+
bool send_gossipsub_message(const std::string& peer_id, GossipSubMessageType type, const nlohmann::json& payload);
|
|
388
|
+
bool broadcast_gossipsub_message(GossipSubMessageType type, const nlohmann::json& payload, const std::unordered_set<std::string>& exclude = {});
|
|
389
|
+
|
|
390
|
+
// Validation
|
|
391
|
+
ValidationResult validate_message(const std::string& topic, const std::string& message, const std::string& sender_peer_id);
|
|
392
|
+
bool is_peer_score_acceptable(const std::string& peer_id, double threshold);
|
|
393
|
+
|
|
394
|
+
// Topic utilities
|
|
395
|
+
TopicSubscription* get_or_create_topic(const std::string& topic);
|
|
396
|
+
void cleanup_topic(const std::string& topic);
|
|
397
|
+
|
|
398
|
+
// Random selection utilities
|
|
399
|
+
std::vector<std::string> random_sample(const std::vector<std::string>& peers, int count);
|
|
400
|
+
std::vector<std::string> random_sample(const std::unordered_set<std::string>& peers, int count);
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
} // namespace librats
|