librats 0.7.0 → 0.7.2
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/lib/index.d.ts +15 -0
- package/native-src/CMakeLists.txt +5 -0
- package/native-src/src/bt_client.cpp +18 -5
- package/native-src/src/bt_client.h +3 -1
- package/native-src/src/bt_network.cpp +1 -1
- package/native-src/src/bt_peer_connection.cpp +11 -0
- package/native-src/src/bt_peer_connection.h +6 -0
- package/native-src/src/bt_torrent.cpp +17 -6
- package/native-src/src/bt_torrent.h +1 -0
- package/native-src/src/bt_types.h +287 -20
- package/native-src/src/dht.cpp +26 -8
- package/native-src/src/dht.h +1 -1
- package/native-src/src/ice.cpp +1 -1
- package/native-src/src/krpc.cpp +8 -1
- package/native-src/src/krpc.h +3 -2
- package/native-src/src/librats.cpp +162 -74
- package/native-src/src/librats.h +43 -6
- package/native-src/src/librats_bittorrent.cpp +3 -2
- package/native-src/src/librats_c.cpp +20 -0
- package/native-src/src/librats_c.h +4 -0
- package/native-src/src/librats_encryption.cpp +5 -0
- package/native-src/src/librats_logging.cpp +21 -0
- package/native-src/src/logger.h +64 -12
- package/native-src/src/network_utils.cpp +175 -373
- package/native-src/src/network_utils.h +2 -113
- package/native-src/src/socket.cpp +485 -883
- package/native-src/src/socket.h +36 -130
- package/native-src/src/stun.cpp +3 -5
- package/native-src/src/tracker.cpp +3 -2
- package/native-src/src/turn.cpp +4 -6
- package/package.json +1 -1
- package/src/librats_node.cpp +23 -0
package/native-src/src/librats.h
CHANGED
|
@@ -48,9 +48,10 @@ struct RatsPeer {
|
|
|
48
48
|
// Handshake-related fields
|
|
49
49
|
enum class HandshakeState {
|
|
50
50
|
PENDING, // Handshake not started
|
|
51
|
-
SENT,
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
SENT, // Handshake sent, waiting for response
|
|
52
|
+
NOISE_PENDING, // Rats handshake done, Noise handshake in progress
|
|
53
|
+
COMPLETED, // Handshake completed successfully (including Noise if enabled)
|
|
54
|
+
FAILED // Handshake failed
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
HandshakeState handshake_state; // Current handshake state
|
|
@@ -635,6 +636,13 @@ public:
|
|
|
635
636
|
*/
|
|
636
637
|
bool is_automatic_discovery_running() const;
|
|
637
638
|
|
|
639
|
+
/**
|
|
640
|
+
* Calculate discovery interval based on current peer count
|
|
641
|
+
* Uses graduated scaling: more aggressive when fewer peers, less aggressive when nearly full
|
|
642
|
+
* @return Discovery interval in seconds
|
|
643
|
+
*/
|
|
644
|
+
std::chrono::seconds calculate_discovery_interval() const;
|
|
645
|
+
|
|
638
646
|
/**
|
|
639
647
|
* Get the discovery hash for current protocol configuration
|
|
640
648
|
* @return Discovery hash based on current protocol name and version
|
|
@@ -990,6 +998,20 @@ public:
|
|
|
990
998
|
// Logging Control API
|
|
991
999
|
// =========================================================================
|
|
992
1000
|
|
|
1001
|
+
/**
|
|
1002
|
+
* Enable or disable console logging
|
|
1003
|
+
* When disabled, log messages will not be printed to stdout/stderr
|
|
1004
|
+
* File logging (if enabled) will still work
|
|
1005
|
+
* @param enabled Whether to enable console logging (default: true)
|
|
1006
|
+
*/
|
|
1007
|
+
void set_console_logging_enabled(bool enabled);
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* Check if console logging is currently enabled
|
|
1011
|
+
* @return true if console logging is enabled
|
|
1012
|
+
*/
|
|
1013
|
+
bool is_console_logging_enabled() const;
|
|
1014
|
+
|
|
993
1015
|
/**
|
|
994
1016
|
* Enable or disable file logging
|
|
995
1017
|
* When enabled, logs will be written to "rats.log" by default
|
|
@@ -1069,6 +1091,20 @@ public:
|
|
|
1069
1091
|
*/
|
|
1070
1092
|
void set_log_retention_count(int count);
|
|
1071
1093
|
|
|
1094
|
+
/**
|
|
1095
|
+
* Enable or disable log rotation on application startup
|
|
1096
|
+
* When enabled, the existing log file will be rotated when logging starts,
|
|
1097
|
+
* so each application run gets a fresh log file
|
|
1098
|
+
* @param enabled Whether to rotate logs on startup (default: false)
|
|
1099
|
+
*/
|
|
1100
|
+
void set_log_rotate_on_startup(bool enabled);
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Check if log rotation on startup is enabled
|
|
1104
|
+
* @return true if rotate on startup is enabled
|
|
1105
|
+
*/
|
|
1106
|
+
bool is_log_rotate_on_startup_enabled() const;
|
|
1107
|
+
|
|
1072
1108
|
/**
|
|
1073
1109
|
* Clear/reset the current log file
|
|
1074
1110
|
*/
|
|
@@ -2046,15 +2082,16 @@ private:
|
|
|
2046
2082
|
std::string message_type;
|
|
2047
2083
|
int64_t timestamp;
|
|
2048
2084
|
bool encryption_enabled; // Whether peer supports/wants encryption
|
|
2085
|
+
uint16_t listen_port; // Peer's listening port for peer exchange
|
|
2049
2086
|
};
|
|
2050
2087
|
|
|
2051
2088
|
std::string create_handshake_message(const std::string& message_type, const std::string& our_peer_id) const;
|
|
2052
|
-
bool parse_handshake_message(const std::
|
|
2089
|
+
bool parse_handshake_message(const std::vector<uint8_t>& data, HandshakeMessage& out_msg) const;
|
|
2053
2090
|
bool validate_handshake_message(const HandshakeMessage& msg) const;
|
|
2054
|
-
bool is_handshake_message(const std::
|
|
2091
|
+
bool is_handshake_message(const std::vector<uint8_t>& data) const;
|
|
2055
2092
|
bool send_handshake(socket_t socket, const std::string& our_peer_id);
|
|
2056
2093
|
bool send_handshake_unlocked(socket_t socket, const std::string& our_peer_id);
|
|
2057
|
-
bool handle_handshake_message(socket_t socket, const std::string& peer_hash_id, const std::
|
|
2094
|
+
bool handle_handshake_message(socket_t socket, const std::string& peer_hash_id, const std::vector<uint8_t>& data);
|
|
2058
2095
|
void check_handshake_timeouts();
|
|
2059
2096
|
void log_handshake_completion_unlocked(const RatsPeer& peer);
|
|
2060
2097
|
|
|
@@ -248,12 +248,13 @@ void RatsClient::get_torrent_metadata_from_peer(const InfoHash& info_hash,
|
|
|
248
248
|
return;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
LOG_CLIENT_INFO("Fetching metadata from peer " << peer_ip << ":" << peer_port << " (fast path)");
|
|
251
|
+
LOG_CLIENT_INFO("Fetching metadata from peer " << peer_ip << ":" << peer_port << " (fast path, no DHT)");
|
|
252
252
|
|
|
253
253
|
// Add magnet in metadata-only mode (empty save_path) and immediately add the peer
|
|
254
|
+
// skip_dht_search=true to avoid network-wide DHT queries - we only want this specific peer
|
|
254
255
|
std::string hash_hex = info_hash_to_hex(info_hash);
|
|
255
256
|
std::string magnet = "magnet:?xt=urn:btih:" + hash_hex;
|
|
256
|
-
auto torrent = bittorrent_client_->add_magnet(magnet, "");
|
|
257
|
+
auto torrent = bittorrent_client_->add_magnet(magnet, "", true /* skip_dht_search */);
|
|
257
258
|
|
|
258
259
|
if (!torrent) {
|
|
259
260
|
if (callback) {
|
|
@@ -161,6 +161,14 @@ char* rats_get_connection_statistics_json(rats_client_t handle) {
|
|
|
161
161
|
return rats_strdup_owned(json.dump());
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
void rats_set_console_logging_enabled(int enabled) {
|
|
165
|
+
Logger::getInstance().set_console_logging_enabled(enabled != 0);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
int rats_is_console_logging_enabled(void) {
|
|
169
|
+
return Logger::getInstance().is_console_logging_enabled() ? 1 : 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
164
172
|
void rats_set_logging_enabled(int enabled) {
|
|
165
173
|
// Global logger control through any client instance is awkward; use singleton
|
|
166
174
|
Logger::getInstance().set_file_logging_enabled(enabled != 0);
|
|
@@ -229,6 +237,18 @@ void rats_set_log_retention_count(rats_client_t handle, int count) {
|
|
|
229
237
|
wrap->client->set_log_retention_count(count);
|
|
230
238
|
}
|
|
231
239
|
|
|
240
|
+
void rats_set_log_rotate_on_startup(rats_client_t handle, int enabled) {
|
|
241
|
+
if (!handle) return;
|
|
242
|
+
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
243
|
+
wrap->client->set_log_rotate_on_startup(enabled != 0);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
int rats_is_log_rotate_on_startup_enabled(rats_client_t handle) {
|
|
247
|
+
if (!handle) return 0;
|
|
248
|
+
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
249
|
+
return wrap->client->is_log_rotate_on_startup_enabled() ? 1 : 0;
|
|
250
|
+
}
|
|
251
|
+
|
|
232
252
|
void rats_clear_log_file(rats_client_t handle) {
|
|
233
253
|
if (!handle) return;
|
|
234
254
|
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
@@ -41,6 +41,8 @@ RATS_API char** rats_get_peer_ids(rats_client_t client, int* count); // caller m
|
|
|
41
41
|
RATS_API char* rats_get_peer_info_json(rats_client_t client, const char* peer_id); // caller must free
|
|
42
42
|
|
|
43
43
|
// Logging controls (optional helpers)
|
|
44
|
+
RATS_API void rats_set_console_logging_enabled(int enabled);
|
|
45
|
+
RATS_API int rats_is_console_logging_enabled(void);
|
|
44
46
|
RATS_API void rats_set_logging_enabled(int enabled);
|
|
45
47
|
RATS_API void rats_set_log_level(const char* level_str); // "DEBUG", "INFO", "WARN", "ERROR"
|
|
46
48
|
RATS_API void rats_set_log_file_path(rats_client_t client, const char* file_path);
|
|
@@ -51,6 +53,8 @@ RATS_API void rats_set_log_timestamps_enabled(rats_client_t client, int enabled)
|
|
|
51
53
|
RATS_API int rats_is_log_timestamps_enabled(rats_client_t client);
|
|
52
54
|
RATS_API void rats_set_log_rotation_size(rats_client_t client, size_t max_size_bytes);
|
|
53
55
|
RATS_API void rats_set_log_retention_count(rats_client_t client, int count);
|
|
56
|
+
RATS_API void rats_set_log_rotate_on_startup(rats_client_t client, int enabled);
|
|
57
|
+
RATS_API int rats_is_log_rotate_on_startup_enabled(rats_client_t client);
|
|
54
58
|
RATS_API void rats_clear_log_file(rats_client_t client);
|
|
55
59
|
|
|
56
60
|
// Error codes
|
|
@@ -103,6 +103,11 @@ std::vector<uint8_t> RatsClient::get_peer_handshake_hash(const std::string& peer
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
bool RatsClient::send_noise_message(socket_t socket, const uint8_t* data, size_t len) {
|
|
106
|
+
// Get socket-specific mutex for thread-safe sending
|
|
107
|
+
// This prevents race conditions with other threads sending rats protocol messages
|
|
108
|
+
auto socket_mutex = get_socket_send_mutex(socket);
|
|
109
|
+
std::lock_guard<std::mutex> send_lock(*socket_mutex);
|
|
110
|
+
|
|
106
111
|
// Send length-prefixed message for Noise handshake
|
|
107
112
|
uint32_t network_len = htonl(static_cast<uint32_t>(len));
|
|
108
113
|
|
|
@@ -14,6 +14,18 @@ namespace librats {
|
|
|
14
14
|
// Logging Control API Implementation
|
|
15
15
|
//=============================================================================
|
|
16
16
|
|
|
17
|
+
void RatsClient::set_console_logging_enabled(bool enabled) {
|
|
18
|
+
Logger::getInstance().set_console_logging_enabled(enabled);
|
|
19
|
+
// Only log if console is enabled, otherwise we're silently disabling
|
|
20
|
+
if (enabled) {
|
|
21
|
+
LOG_CLIENT_INFO("Console logging enabled");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
bool RatsClient::is_console_logging_enabled() const {
|
|
26
|
+
return Logger::getInstance().is_console_logging_enabled();
|
|
27
|
+
}
|
|
28
|
+
|
|
17
29
|
void RatsClient::set_logging_enabled(bool enabled) {
|
|
18
30
|
LOG_CLIENT_INFO("Setting file logging " << (enabled ? "enabled" : "disabled"));
|
|
19
31
|
|
|
@@ -124,6 +136,15 @@ void RatsClient::set_log_retention_count(int count) {
|
|
|
124
136
|
LOG_CLIENT_INFO("Log retention count set to: " << count << " files");
|
|
125
137
|
}
|
|
126
138
|
|
|
139
|
+
void RatsClient::set_log_rotate_on_startup(bool enabled) {
|
|
140
|
+
Logger::getInstance().set_rotate_on_startup(enabled);
|
|
141
|
+
LOG_CLIENT_INFO("Log rotation on startup " << (enabled ? "enabled" : "disabled"));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
bool RatsClient::is_log_rotate_on_startup_enabled() const {
|
|
145
|
+
return Logger::getInstance().is_rotate_on_startup_enabled();
|
|
146
|
+
}
|
|
147
|
+
|
|
127
148
|
void RatsClient::clear_log_file() {
|
|
128
149
|
Logger& logger = Logger::getInstance();
|
|
129
150
|
std::string log_path = logger.get_log_file_path();
|
package/native-src/src/logger.h
CHANGED
|
@@ -59,6 +59,17 @@ public:
|
|
|
59
59
|
timestamps_enabled_ = enabled;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// Console logging configuration
|
|
63
|
+
void set_console_logging_enabled(bool enabled) {
|
|
64
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
65
|
+
console_logging_enabled_ = enabled;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
bool is_console_logging_enabled() const {
|
|
69
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
70
|
+
return console_logging_enabled_;
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
// File logging configuration
|
|
63
74
|
void set_file_logging_enabled(bool enabled) {
|
|
64
75
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
@@ -89,6 +100,17 @@ public:
|
|
|
89
100
|
max_log_files_ = count;
|
|
90
101
|
}
|
|
91
102
|
|
|
103
|
+
// Rotate on startup configuration
|
|
104
|
+
void set_rotate_on_startup(bool enabled) {
|
|
105
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
106
|
+
rotate_on_startup_ = enabled;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
bool is_rotate_on_startup_enabled() const {
|
|
110
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
111
|
+
return rotate_on_startup_;
|
|
112
|
+
}
|
|
113
|
+
|
|
92
114
|
// Get current file logging status
|
|
93
115
|
bool is_file_logging_enabled() const {
|
|
94
116
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
@@ -147,13 +169,15 @@ public:
|
|
|
147
169
|
// Add message
|
|
148
170
|
console_oss << " " << message << std::endl;
|
|
149
171
|
|
|
150
|
-
// Output to appropriate console stream
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
172
|
+
// Output to appropriate console stream (if console logging is enabled)
|
|
173
|
+
if (console_logging_enabled_) {
|
|
174
|
+
if (level >= LogLevel::ERROR) {
|
|
175
|
+
std::cerr << console_oss.str();
|
|
176
|
+
std::cerr.flush();
|
|
177
|
+
} else {
|
|
178
|
+
std::cout << console_oss.str();
|
|
179
|
+
std::cout.flush();
|
|
180
|
+
}
|
|
157
181
|
}
|
|
158
182
|
|
|
159
183
|
// Also write to file if file logging is enabled
|
|
@@ -164,8 +188,9 @@ public:
|
|
|
164
188
|
|
|
165
189
|
private:
|
|
166
190
|
Logger() : min_level_(LogLevel::INFO), colors_enabled_(true), timestamps_enabled_(true),
|
|
167
|
-
|
|
168
|
-
max_log_files_(5), current_file_size_(0)
|
|
191
|
+
console_logging_enabled_(true), file_logging_enabled_(false),
|
|
192
|
+
max_log_file_size_(10 * 1024 * 1024), max_log_files_(5), current_file_size_(0),
|
|
193
|
+
rotate_on_startup_(false), startup_rotation_done_(false) {
|
|
169
194
|
// Check if we're outputting to a terminal
|
|
170
195
|
is_terminal_ = isatty(fileno(stdout));
|
|
171
196
|
|
|
@@ -317,6 +342,19 @@ private:
|
|
|
317
342
|
}
|
|
318
343
|
}
|
|
319
344
|
|
|
345
|
+
// Perform rotation on startup if enabled and not yet done this session
|
|
346
|
+
if (rotate_on_startup_ && !startup_rotation_done_) {
|
|
347
|
+
// Check if the log file exists and has content
|
|
348
|
+
if (file_exists(log_file_path_.c_str())) {
|
|
349
|
+
std::ifstream check_file(log_file_path_, std::ios::ate);
|
|
350
|
+
if (check_file.is_open() && check_file.tellg() > 0) {
|
|
351
|
+
check_file.close();
|
|
352
|
+
rotate_log_files_impl();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
startup_rotation_done_ = true;
|
|
356
|
+
}
|
|
357
|
+
|
|
320
358
|
log_file_.open(log_file_path_, std::ios::app);
|
|
321
359
|
if (log_file_.is_open()) {
|
|
322
360
|
// Get current file size
|
|
@@ -337,6 +375,16 @@ private:
|
|
|
337
375
|
if (log_file_path_.empty() || max_log_files_ <= 0) return;
|
|
338
376
|
|
|
339
377
|
close_log_file();
|
|
378
|
+
rotate_log_files_impl();
|
|
379
|
+
|
|
380
|
+
// Reopen the log file (new empty file)
|
|
381
|
+
open_log_file();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Internal rotation implementation - does not close/open files
|
|
385
|
+
// Called directly when we need to rotate before opening (e.g., on startup)
|
|
386
|
+
void rotate_log_files_impl() {
|
|
387
|
+
if (log_file_path_.empty() || max_log_files_ <= 0) return;
|
|
340
388
|
|
|
341
389
|
// Move existing log files
|
|
342
390
|
for (int i = max_log_files_ - 1; i >= 1; i--) {
|
|
@@ -355,9 +403,6 @@ private:
|
|
|
355
403
|
// Move current log file to .1
|
|
356
404
|
std::string backup_name = log_file_path_ + ".1";
|
|
357
405
|
std::rename(log_file_path_.c_str(), backup_name.c_str());
|
|
358
|
-
|
|
359
|
-
// Reopen the log file (new empty file)
|
|
360
|
-
open_log_file();
|
|
361
406
|
}
|
|
362
407
|
|
|
363
408
|
mutable std::mutex mutex_;
|
|
@@ -366,6 +411,9 @@ private:
|
|
|
366
411
|
bool timestamps_enabled_;
|
|
367
412
|
bool is_terminal_;
|
|
368
413
|
|
|
414
|
+
// Console logging control
|
|
415
|
+
bool console_logging_enabled_;
|
|
416
|
+
|
|
369
417
|
// File logging members
|
|
370
418
|
bool file_logging_enabled_;
|
|
371
419
|
std::string log_file_path_;
|
|
@@ -373,6 +421,10 @@ private:
|
|
|
373
421
|
size_t max_log_file_size_;
|
|
374
422
|
int max_log_files_;
|
|
375
423
|
size_t current_file_size_;
|
|
424
|
+
|
|
425
|
+
// Rotate on startup members
|
|
426
|
+
bool rotate_on_startup_;
|
|
427
|
+
bool startup_rotation_done_; // Tracks if we've already done startup rotation for this session
|
|
376
428
|
};
|
|
377
429
|
|
|
378
430
|
} // namespace librats
|