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,293 @@
|
|
|
1
|
+
#include "librats.h"
|
|
2
|
+
// Logging macros for RatsClient
|
|
3
|
+
#define LOG_CLIENT_DEBUG(message) LOG_DEBUG("client", message)
|
|
4
|
+
#define LOG_CLIENT_INFO(message) LOG_INFO("client", message)
|
|
5
|
+
#define LOG_CLIENT_WARN(message) LOG_WARN("client", message)
|
|
6
|
+
#define LOG_CLIENT_ERROR(message) LOG_ERROR("client", message)
|
|
7
|
+
|
|
8
|
+
namespace librats {
|
|
9
|
+
|
|
10
|
+
//=============================================================================
|
|
11
|
+
// GossipSub Integration Methods
|
|
12
|
+
//=============================================================================
|
|
13
|
+
|
|
14
|
+
GossipSub& RatsClient::get_gossipsub() {
|
|
15
|
+
if (!gossipsub_) {
|
|
16
|
+
throw std::runtime_error("GossipSub not initialized");
|
|
17
|
+
}
|
|
18
|
+
return *gossipsub_;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
bool RatsClient::is_gossipsub_available() const {
|
|
22
|
+
return gossipsub_ != nullptr;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//=============================================================================
|
|
26
|
+
// GossipSub Convenience Methods - Topic Management
|
|
27
|
+
//=============================================================================
|
|
28
|
+
|
|
29
|
+
bool RatsClient::subscribe_to_topic(const std::string& topic) {
|
|
30
|
+
if (!is_gossipsub_available()) {
|
|
31
|
+
LOG_CLIENT_ERROR("GossipSub not available for topic subscription: " << topic);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
return gossipsub_->subscribe(topic);
|
|
37
|
+
} catch (const std::exception& e) {
|
|
38
|
+
LOG_CLIENT_ERROR("Failed to subscribe to topic '" << topic << "': " << e.what());
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
bool RatsClient::unsubscribe_from_topic(const std::string& topic) {
|
|
44
|
+
if (!is_gossipsub_available()) {
|
|
45
|
+
LOG_CLIENT_ERROR("GossipSub not available for topic unsubscription: " << topic);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
return gossipsub_->unsubscribe(topic);
|
|
51
|
+
} catch (const std::exception& e) {
|
|
52
|
+
LOG_CLIENT_ERROR("Failed to unsubscribe from topic '" << topic << "': " << e.what());
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bool RatsClient::is_subscribed_to_topic(const std::string& topic) const {
|
|
58
|
+
if (!is_gossipsub_available()) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
return gossipsub_->is_subscribed(topic);
|
|
64
|
+
} catch (const std::exception& e) {
|
|
65
|
+
LOG_CLIENT_ERROR("Failed to check subscription for topic '" << topic << "': " << e.what());
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
std::vector<std::string> RatsClient::get_subscribed_topics() const {
|
|
71
|
+
if (!is_gossipsub_available()) {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
return gossipsub_->get_subscribed_topics();
|
|
77
|
+
} catch (const std::exception& e) {
|
|
78
|
+
LOG_CLIENT_ERROR("Failed to get subscribed topics: " << e.what());
|
|
79
|
+
return {};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//=============================================================================
|
|
84
|
+
// GossipSub Convenience Methods - Publishing
|
|
85
|
+
//=============================================================================
|
|
86
|
+
|
|
87
|
+
bool RatsClient::publish_to_topic(const std::string& topic, const std::string& message) {
|
|
88
|
+
if (!is_gossipsub_available()) {
|
|
89
|
+
LOG_CLIENT_ERROR("GossipSub not available for publishing to topic: " << topic);
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
return gossipsub_->publish(topic, message);
|
|
95
|
+
} catch (const std::exception& e) {
|
|
96
|
+
LOG_CLIENT_ERROR("Failed to publish to topic '" << topic << "': " << e.what());
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
bool RatsClient::publish_json_to_topic(const std::string& topic, const nlohmann::json& message) {
|
|
102
|
+
if (!is_gossipsub_available()) {
|
|
103
|
+
LOG_CLIENT_ERROR("GossipSub not available for publishing JSON to topic: " << topic);
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
return gossipsub_->publish(topic, message);
|
|
109
|
+
} catch (const std::exception& e) {
|
|
110
|
+
LOG_CLIENT_ERROR("Failed to publish JSON to topic '" << topic << "': " << e.what());
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
//=============================================================================
|
|
116
|
+
// GossipSub Convenience Methods - Event Handlers (Unified API)
|
|
117
|
+
//=============================================================================
|
|
118
|
+
|
|
119
|
+
void RatsClient::on_topic_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const std::string&)> callback) {
|
|
120
|
+
if (!is_gossipsub_available()) {
|
|
121
|
+
LOG_CLIENT_ERROR("GossipSub not available for setting message handler on topic: " << topic);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
// Convert unified callback signature to GossipSub's MessageHandler signature
|
|
127
|
+
gossipsub_->set_message_handler(topic, [callback](const std::string& topic, const std::string& message, const std::string& sender_peer_id) {
|
|
128
|
+
callback(sender_peer_id, topic, message);
|
|
129
|
+
});
|
|
130
|
+
LOG_CLIENT_INFO("Set message handler for topic: " << topic);
|
|
131
|
+
} catch (const std::exception& e) {
|
|
132
|
+
LOG_CLIENT_ERROR("Failed to set message handler for topic '" << topic << "': " << e.what());
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void RatsClient::on_topic_json_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const nlohmann::json&)> callback) {
|
|
137
|
+
if (!is_gossipsub_available()) {
|
|
138
|
+
LOG_CLIENT_ERROR("GossipSub not available for setting JSON message handler on topic: " << topic);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
// Convert unified callback signature to GossipSub's MessageHandler signature with JSON parsing
|
|
144
|
+
gossipsub_->set_message_handler(topic, [callback](const std::string& topic, const std::string& message, const std::string& sender_peer_id) {
|
|
145
|
+
try {
|
|
146
|
+
nlohmann::json json_message = nlohmann::json::parse(message);
|
|
147
|
+
callback(sender_peer_id, topic, json_message);
|
|
148
|
+
} catch (const nlohmann::json::exception& e) {
|
|
149
|
+
LOG_WARN("client", "Failed to parse JSON message on topic '" << topic << "': " << e.what());
|
|
150
|
+
// Still call callback with empty JSON object to maintain consistency
|
|
151
|
+
callback(sender_peer_id, topic, nlohmann::json{});
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
LOG_CLIENT_INFO("Set JSON message handler for topic: " << topic);
|
|
155
|
+
} catch (const std::exception& e) {
|
|
156
|
+
LOG_CLIENT_ERROR("Failed to set JSON message handler for topic '" << topic << "': " << e.what());
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
void RatsClient::on_topic_peer_joined(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback) {
|
|
161
|
+
if (!is_gossipsub_available()) {
|
|
162
|
+
LOG_CLIENT_ERROR("GossipSub not available for setting peer joined handler on topic: " << topic);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
// Convert unified callback signature to GossipSub's PeerJoinedHandler signature
|
|
168
|
+
gossipsub_->set_peer_joined_handler(topic, [callback](const std::string& topic, const std::string& peer_id) {
|
|
169
|
+
callback(peer_id, topic);
|
|
170
|
+
});
|
|
171
|
+
LOG_CLIENT_INFO("Set peer joined handler for topic: " << topic);
|
|
172
|
+
} catch (const std::exception& e) {
|
|
173
|
+
LOG_CLIENT_ERROR("Failed to set peer joined handler for topic '" << topic << "': " << e.what());
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
void RatsClient::on_topic_peer_left(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback) {
|
|
178
|
+
if (!is_gossipsub_available()) {
|
|
179
|
+
LOG_CLIENT_ERROR("GossipSub not available for setting peer left handler on topic: " << topic);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// Convert unified callback signature to GossipSub's PeerLeftHandler signature
|
|
185
|
+
gossipsub_->set_peer_left_handler(topic, [callback](const std::string& topic, const std::string& peer_id) {
|
|
186
|
+
callback(peer_id, topic);
|
|
187
|
+
});
|
|
188
|
+
LOG_CLIENT_INFO("Set peer left handler for topic: " << topic);
|
|
189
|
+
} catch (const std::exception& e) {
|
|
190
|
+
LOG_CLIENT_ERROR("Failed to set peer left handler for topic '" << topic << "': " << e.what());
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
void RatsClient::set_topic_message_validator(const std::string& topic, std::function<ValidationResult(const std::string&, const std::string&, const std::string&)> validator) {
|
|
195
|
+
if (!is_gossipsub_available()) {
|
|
196
|
+
LOG_CLIENT_ERROR("GossipSub not available for setting message validator on topic: " << topic);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
// Convert unified callback signature to GossipSub's MessageValidator signature
|
|
202
|
+
gossipsub_->set_message_validator(topic, [validator](const std::string& topic, const std::string& message, const std::string& sender_peer_id) {
|
|
203
|
+
return validator(topic, message, sender_peer_id);
|
|
204
|
+
});
|
|
205
|
+
LOG_CLIENT_INFO("Set message validator for topic: " << topic);
|
|
206
|
+
} catch (const std::exception& e) {
|
|
207
|
+
LOG_CLIENT_ERROR("Failed to set message validator for topic '" << topic << "': " << e.what());
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
void RatsClient::off_topic(const std::string& topic) {
|
|
212
|
+
if (!is_gossipsub_available()) {
|
|
213
|
+
LOG_CLIENT_ERROR("GossipSub not available for removing handlers from topic: " << topic);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
// Remove all handlers by setting them to nullptr
|
|
219
|
+
gossipsub_->set_message_handler(topic, nullptr);
|
|
220
|
+
gossipsub_->set_peer_joined_handler(topic, nullptr);
|
|
221
|
+
gossipsub_->set_peer_left_handler(topic, nullptr);
|
|
222
|
+
gossipsub_->set_message_validator(topic, nullptr);
|
|
223
|
+
LOG_CLIENT_INFO("Removed all handlers for topic: " << topic);
|
|
224
|
+
} catch (const std::exception& e) {
|
|
225
|
+
LOG_CLIENT_ERROR("Failed to remove handlers for topic '" << topic << "': " << e.what());
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
//=============================================================================
|
|
230
|
+
// GossipSub Convenience Methods - Information
|
|
231
|
+
//=============================================================================
|
|
232
|
+
|
|
233
|
+
std::vector<std::string> RatsClient::get_topic_peers(const std::string& topic) const {
|
|
234
|
+
if (!is_gossipsub_available()) {
|
|
235
|
+
return {};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
return gossipsub_->get_topic_peers(topic);
|
|
240
|
+
} catch (const std::exception& e) {
|
|
241
|
+
LOG_CLIENT_ERROR("Failed to get topic peers for '" << topic << "': " << e.what());
|
|
242
|
+
return {};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
std::vector<std::string> RatsClient::get_topic_mesh_peers(const std::string& topic) const {
|
|
247
|
+
if (!is_gossipsub_available()) {
|
|
248
|
+
return {};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
return gossipsub_->get_mesh_peers(topic);
|
|
253
|
+
} catch (const std::exception& e) {
|
|
254
|
+
LOG_CLIENT_ERROR("Failed to get mesh peers for topic '" << topic << "': " << e.what());
|
|
255
|
+
return {};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
nlohmann::json RatsClient::get_gossipsub_statistics() const {
|
|
260
|
+
if (!is_gossipsub_available()) {
|
|
261
|
+
nlohmann::json empty_stats;
|
|
262
|
+
empty_stats["available"] = false;
|
|
263
|
+
empty_stats["error"] = "GossipSub not initialized";
|
|
264
|
+
return empty_stats;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
nlohmann::json stats = gossipsub_->get_statistics();
|
|
269
|
+
stats["available"] = true;
|
|
270
|
+
stats["running"] = gossipsub_->is_running();
|
|
271
|
+
return stats;
|
|
272
|
+
} catch (const std::exception& e) {
|
|
273
|
+
nlohmann::json error_stats;
|
|
274
|
+
error_stats["available"] = true;
|
|
275
|
+
error_stats["error"] = e.what();
|
|
276
|
+
return error_stats;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
bool RatsClient::is_gossipsub_running() const {
|
|
281
|
+
if (!is_gossipsub_available()) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
try {
|
|
286
|
+
return gossipsub_->is_running();
|
|
287
|
+
} catch (const std::exception& e) {
|
|
288
|
+
LOG_CLIENT_ERROR("Failed to check GossipSub running status: " << e.what());
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
}
|