librats 0.3.1 → 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.
Files changed (69) hide show
  1. package/README.md +405 -405
  2. package/binding.gyp +96 -95
  3. package/lib/index.d.ts +522 -522
  4. package/lib/index.js +82 -82
  5. package/native-src/3rdparty/android/ifaddrs-android.c +600 -0
  6. package/native-src/3rdparty/android/ifaddrs-android.h +54 -0
  7. package/native-src/CMakeLists.txt +360 -0
  8. package/native-src/LICENSE +21 -0
  9. package/native-src/src/bencode.cpp +485 -0
  10. package/native-src/src/bencode.h +145 -0
  11. package/native-src/src/bittorrent.cpp +3682 -0
  12. package/native-src/src/bittorrent.h +731 -0
  13. package/native-src/src/dht.cpp +2342 -0
  14. package/native-src/src/dht.h +501 -0
  15. package/native-src/src/encrypted_socket.cpp +817 -0
  16. package/native-src/src/encrypted_socket.h +239 -0
  17. package/native-src/src/file_transfer.cpp +1808 -0
  18. package/native-src/src/file_transfer.h +567 -0
  19. package/native-src/src/fs.cpp +639 -0
  20. package/native-src/src/fs.h +108 -0
  21. package/native-src/src/gossipsub.cpp +1137 -0
  22. package/native-src/src/gossipsub.h +403 -0
  23. package/native-src/src/ice.cpp +1386 -0
  24. package/native-src/src/ice.h +328 -0
  25. package/native-src/src/json.hpp +25526 -0
  26. package/native-src/src/krpc.cpp +558 -0
  27. package/native-src/src/krpc.h +145 -0
  28. package/native-src/src/librats.cpp +2715 -0
  29. package/native-src/src/librats.h +1729 -0
  30. package/native-src/src/librats_bittorrent.cpp +167 -0
  31. package/native-src/src/librats_c.cpp +1317 -0
  32. package/native-src/src/librats_c.h +237 -0
  33. package/native-src/src/librats_encryption.cpp +123 -0
  34. package/native-src/src/librats_file_transfer.cpp +226 -0
  35. package/native-src/src/librats_gossipsub.cpp +293 -0
  36. package/native-src/src/librats_ice.cpp +515 -0
  37. package/native-src/src/librats_logging.cpp +158 -0
  38. package/native-src/src/librats_mdns.cpp +171 -0
  39. package/native-src/src/librats_nat.cpp +571 -0
  40. package/native-src/src/librats_persistence.cpp +815 -0
  41. package/native-src/src/logger.h +412 -0
  42. package/native-src/src/mdns.cpp +1178 -0
  43. package/native-src/src/mdns.h +253 -0
  44. package/native-src/src/network_utils.cpp +598 -0
  45. package/native-src/src/network_utils.h +162 -0
  46. package/native-src/src/noise.cpp +981 -0
  47. package/native-src/src/noise.h +227 -0
  48. package/native-src/src/os.cpp +371 -0
  49. package/native-src/src/os.h +40 -0
  50. package/native-src/src/rats_export.h +17 -0
  51. package/native-src/src/sha1.cpp +163 -0
  52. package/native-src/src/sha1.h +42 -0
  53. package/native-src/src/socket.cpp +1376 -0
  54. package/native-src/src/socket.h +309 -0
  55. package/native-src/src/stun.cpp +484 -0
  56. package/native-src/src/stun.h +349 -0
  57. package/native-src/src/threadmanager.cpp +105 -0
  58. package/native-src/src/threadmanager.h +53 -0
  59. package/native-src/src/tracker.cpp +1110 -0
  60. package/native-src/src/tracker.h +268 -0
  61. package/native-src/src/version.cpp +24 -0
  62. package/native-src/src/version.h.in +45 -0
  63. package/native-src/version.rc.in +31 -0
  64. package/package.json +62 -68
  65. package/scripts/build-librats.js +241 -194
  66. package/scripts/postinstall.js +52 -52
  67. package/scripts/prepare-package.js +187 -91
  68. package/scripts/verify-installation.js +119 -119
  69. package/src/librats_node.cpp +1174 -1174
@@ -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