librats 0.5.0 → 0.5.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/README.md +1 -1
- package/binding.gyp +1 -0
- package/lib/index.d.ts +2 -1
- 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 +2460 -0
- package/native-src/src/dht.h +508 -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 +2735 -0
- package/native-src/src/librats.h +1732 -0
- package/native-src/src/librats_bittorrent.cpp +167 -0
- package/native-src/src/librats_c.cpp +1333 -0
- package/native-src/src/librats_c.h +239 -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
- package/src/librats_node.cpp +46 -1
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <iostream>
|
|
5
|
+
#include <mutex>
|
|
6
|
+
#include <sstream>
|
|
7
|
+
#include <chrono>
|
|
8
|
+
#include <iomanip>
|
|
9
|
+
#include <cstdint>
|
|
10
|
+
#include <fstream>
|
|
11
|
+
#include "fs.h"
|
|
12
|
+
|
|
13
|
+
#ifdef _WIN32
|
|
14
|
+
#include <windows.h>
|
|
15
|
+
#include <io.h>
|
|
16
|
+
#define isatty _isatty
|
|
17
|
+
#define fileno _fileno
|
|
18
|
+
// Undefine Windows ERROR macro to avoid conflicts with our enum
|
|
19
|
+
#ifdef ERROR
|
|
20
|
+
#undef ERROR
|
|
21
|
+
#endif
|
|
22
|
+
#else
|
|
23
|
+
#include <unistd.h>
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
namespace librats {
|
|
27
|
+
|
|
28
|
+
enum class LogLevel {
|
|
29
|
+
DEBUG = 0,
|
|
30
|
+
INFO = 1,
|
|
31
|
+
WARN = 2,
|
|
32
|
+
ERROR = 3
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
class Logger {
|
|
36
|
+
public:
|
|
37
|
+
// Singleton pattern
|
|
38
|
+
static Logger& getInstance() {
|
|
39
|
+
static Logger instance;
|
|
40
|
+
return instance;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Delete copy constructor and assignment operator
|
|
44
|
+
Logger(const Logger&) = delete;
|
|
45
|
+
Logger& operator=(const Logger&) = delete;
|
|
46
|
+
|
|
47
|
+
// Set the minimum log level
|
|
48
|
+
void set_log_level(LogLevel level) {
|
|
49
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
50
|
+
min_level_ = level;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Enable/disable colors
|
|
54
|
+
void set_colors_enabled(bool enabled) {
|
|
55
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
56
|
+
colors_enabled_ = enabled;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Enable/disable timestamps
|
|
60
|
+
void set_timestamps_enabled(bool enabled) {
|
|
61
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
62
|
+
timestamps_enabled_ = enabled;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// File logging configuration
|
|
66
|
+
void set_file_logging_enabled(bool enabled) {
|
|
67
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
68
|
+
file_logging_enabled_ = enabled;
|
|
69
|
+
if (enabled && !log_file_path_.empty()) {
|
|
70
|
+
open_log_file();
|
|
71
|
+
} else if (!enabled) {
|
|
72
|
+
close_log_file();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void set_log_file_path(const std::string& path) {
|
|
77
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
78
|
+
log_file_path_ = path;
|
|
79
|
+
if (file_logging_enabled_) {
|
|
80
|
+
close_log_file();
|
|
81
|
+
open_log_file();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void set_log_rotation_size(size_t max_size_bytes) {
|
|
86
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
87
|
+
max_log_file_size_ = max_size_bytes;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void set_log_retention_count(int count) {
|
|
91
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
92
|
+
max_log_files_ = count;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Get current file logging status
|
|
96
|
+
bool is_file_logging_enabled() const {
|
|
97
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
98
|
+
return file_logging_enabled_;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
std::string get_log_file_path() const {
|
|
102
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
103
|
+
return log_file_path_;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Main logging function
|
|
107
|
+
void log(LogLevel level, const std::string& module, const std::string& message) {
|
|
108
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
109
|
+
|
|
110
|
+
if (level < min_level_) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Prepare console output with colors
|
|
115
|
+
std::ostringstream console_oss;
|
|
116
|
+
|
|
117
|
+
// Add timestamp if enabled
|
|
118
|
+
if (timestamps_enabled_) {
|
|
119
|
+
auto now = std::chrono::system_clock::now();
|
|
120
|
+
auto time_t = std::chrono::system_clock::to_time_t(now);
|
|
121
|
+
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
122
|
+
now.time_since_epoch()) % 1000;
|
|
123
|
+
|
|
124
|
+
struct tm local_tm;
|
|
125
|
+
#ifdef _WIN32
|
|
126
|
+
localtime_s(&local_tm, &time_t);
|
|
127
|
+
#else
|
|
128
|
+
local_tm = *std::localtime(&time_t);
|
|
129
|
+
#endif
|
|
130
|
+
console_oss << "[" << std::put_time(&local_tm, "%H:%M:%S");
|
|
131
|
+
console_oss << "." << std::setfill('0') << std::setw(3) << ms.count() << "] ";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add colored log level
|
|
135
|
+
if (colors_enabled_ && is_terminal_) {
|
|
136
|
+
console_oss << get_color_code(level) << "[" << get_level_string(level) << "]" << get_reset_code();
|
|
137
|
+
} else {
|
|
138
|
+
console_oss << "[" << get_level_string(level) << "]";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Add colored module tag
|
|
142
|
+
if (!module.empty()) {
|
|
143
|
+
if (colors_enabled_ && is_terminal_) {
|
|
144
|
+
console_oss << " " << get_module_color(module) << "[" << module << "]" << get_reset_code();
|
|
145
|
+
} else {
|
|
146
|
+
console_oss << " [" << module << "]";
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Add message
|
|
151
|
+
console_oss << " " << message << std::endl;
|
|
152
|
+
|
|
153
|
+
// Output to appropriate console stream
|
|
154
|
+
if (level >= LogLevel::ERROR) {
|
|
155
|
+
std::cerr << console_oss.str();
|
|
156
|
+
std::cerr.flush();
|
|
157
|
+
} else {
|
|
158
|
+
std::cout << console_oss.str();
|
|
159
|
+
std::cout.flush();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Also write to file if file logging is enabled
|
|
163
|
+
if (file_logging_enabled_ && log_file_.is_open()) {
|
|
164
|
+
write_to_file(level, module, message);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private:
|
|
169
|
+
Logger() : min_level_(LogLevel::INFO), colors_enabled_(true), timestamps_enabled_(true),
|
|
170
|
+
file_logging_enabled_(false), max_log_file_size_(10 * 1024 * 1024),
|
|
171
|
+
max_log_files_(5), current_file_size_(0) {
|
|
172
|
+
// Check if we're outputting to a terminal
|
|
173
|
+
is_terminal_ = isatty(fileno(stdout));
|
|
174
|
+
|
|
175
|
+
// On Windows, enable ANSI color codes
|
|
176
|
+
#ifdef _WIN32
|
|
177
|
+
if (is_terminal_) {
|
|
178
|
+
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
179
|
+
DWORD dwMode = 0;
|
|
180
|
+
GetConsoleMode(hOut, &dwMode);
|
|
181
|
+
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
182
|
+
SetConsoleMode(hOut, dwMode);
|
|
183
|
+
}
|
|
184
|
+
#endif
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
~Logger() {
|
|
188
|
+
close_log_file();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
std::string get_level_string(LogLevel level) {
|
|
192
|
+
switch (level) {
|
|
193
|
+
case LogLevel::DEBUG: return "DEBUG";
|
|
194
|
+
case LogLevel::INFO: return "INFO ";
|
|
195
|
+
case LogLevel::WARN: return "WARN ";
|
|
196
|
+
case LogLevel::ERROR: return "ERROR";
|
|
197
|
+
default: return "UNKNOWN";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
std::string get_color_code(LogLevel level) {
|
|
202
|
+
if (!colors_enabled_ || !is_terminal_) return "";
|
|
203
|
+
|
|
204
|
+
switch (level) {
|
|
205
|
+
case LogLevel::DEBUG: return "\033[36m"; // Cyan
|
|
206
|
+
case LogLevel::INFO: return "\033[32m"; // Green
|
|
207
|
+
case LogLevel::WARN: return "\033[33m"; // Yellow
|
|
208
|
+
case LogLevel::ERROR: return "\033[31m"; // Red
|
|
209
|
+
default: return "";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
std::string get_module_color(const std::string& module) {
|
|
214
|
+
if (!colors_enabled_ || !is_terminal_) return "";
|
|
215
|
+
|
|
216
|
+
// Generate hash for module name
|
|
217
|
+
uint32_t hash = hash_string(module);
|
|
218
|
+
|
|
219
|
+
// Map hash to a predefined set of nice, readable colors
|
|
220
|
+
const char* colors[] = {
|
|
221
|
+
"\033[35m", // Magenta
|
|
222
|
+
"\033[36m", // Cyan
|
|
223
|
+
"\033[94m", // Bright Blue
|
|
224
|
+
"\033[95m", // Bright Magenta
|
|
225
|
+
"\033[96m", // Bright Cyan
|
|
226
|
+
"\033[93m", // Bright Yellow
|
|
227
|
+
"\033[91m", // Bright Red
|
|
228
|
+
"\033[92m", // Bright Green
|
|
229
|
+
"\033[90m", // Bright Black (Gray)
|
|
230
|
+
"\033[37m", // White
|
|
231
|
+
"\033[34m", // Blue
|
|
232
|
+
"\033[33m", // Yellow
|
|
233
|
+
"\033[31m", // Red
|
|
234
|
+
"\033[32m", // Green
|
|
235
|
+
"\033[97m", // Bright White
|
|
236
|
+
"\033[38;5;208m", // Orange
|
|
237
|
+
"\033[38;5;165m", // Pink
|
|
238
|
+
"\033[38;5;141m", // Purple
|
|
239
|
+
"\033[38;5;51m", // Bright Turquoise
|
|
240
|
+
"\033[38;5;226m", // Bright Yellow
|
|
241
|
+
"\033[38;5;46m", // Bright Green
|
|
242
|
+
"\033[38;5;196m", // Bright Red
|
|
243
|
+
"\033[38;5;21m", // Bright Blue
|
|
244
|
+
"\033[38;5;129m" // Bright Purple
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
size_t color_count = sizeof(colors) / sizeof(colors[0]);
|
|
248
|
+
return colors[hash % color_count];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Simple hash function for strings
|
|
252
|
+
uint32_t hash_string(const std::string& str) {
|
|
253
|
+
uint32_t hash = 5381;
|
|
254
|
+
for (char c : str) {
|
|
255
|
+
hash = ((hash << 5) + hash) + c; // hash * 33 + c
|
|
256
|
+
}
|
|
257
|
+
return hash;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
std::string get_reset_code() {
|
|
261
|
+
if (!colors_enabled_ || !is_terminal_) return "";
|
|
262
|
+
return "\033[0m";
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// File logging methods
|
|
266
|
+
void write_to_file(LogLevel level, const std::string& module, const std::string& message) {
|
|
267
|
+
if (!log_file_.is_open()) return;
|
|
268
|
+
|
|
269
|
+
// Check if rotation is needed
|
|
270
|
+
if (max_log_file_size_ > 0 && current_file_size_ >= max_log_file_size_) {
|
|
271
|
+
rotate_log_files();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
std::ostringstream file_oss;
|
|
275
|
+
|
|
276
|
+
// Add timestamp (always enabled for file logs)
|
|
277
|
+
auto now = std::chrono::system_clock::now();
|
|
278
|
+
auto time_t = std::chrono::system_clock::to_time_t(now);
|
|
279
|
+
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
280
|
+
now.time_since_epoch()) % 1000;
|
|
281
|
+
|
|
282
|
+
struct tm local_tm;
|
|
283
|
+
#ifdef _WIN32
|
|
284
|
+
localtime_s(&local_tm, &time_t);
|
|
285
|
+
#else
|
|
286
|
+
local_tm = *std::localtime(&time_t);
|
|
287
|
+
#endif
|
|
288
|
+
file_oss << "[" << std::put_time(&local_tm, "%Y-%m-%d %H:%M:%S");
|
|
289
|
+
file_oss << "." << std::setfill('0') << std::setw(3) << ms.count() << "] ";
|
|
290
|
+
|
|
291
|
+
// Add log level (no colors in file)
|
|
292
|
+
file_oss << "[" << get_level_string(level) << "]";
|
|
293
|
+
|
|
294
|
+
// Add module tag
|
|
295
|
+
if (!module.empty()) {
|
|
296
|
+
file_oss << " [" << module << "]";
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Add message
|
|
300
|
+
file_oss << " " << message << std::endl;
|
|
301
|
+
|
|
302
|
+
std::string log_line = file_oss.str();
|
|
303
|
+
log_file_ << log_line;
|
|
304
|
+
log_file_.flush();
|
|
305
|
+
|
|
306
|
+
current_file_size_ += log_line.length();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
void open_log_file() {
|
|
310
|
+
if (log_file_path_.empty()) return;
|
|
311
|
+
|
|
312
|
+
close_log_file();
|
|
313
|
+
|
|
314
|
+
// Create directory if it doesn't exist
|
|
315
|
+
size_t last_slash = log_file_path_.find_last_of("/\\");
|
|
316
|
+
if (last_slash != std::string::npos) {
|
|
317
|
+
std::string dir_path = log_file_path_.substr(0, last_slash);
|
|
318
|
+
if (!directory_exists(dir_path.c_str())) {
|
|
319
|
+
create_directories(dir_path.c_str());
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
log_file_.open(log_file_path_, std::ios::app);
|
|
324
|
+
if (log_file_.is_open()) {
|
|
325
|
+
// Get current file size
|
|
326
|
+
log_file_.seekp(0, std::ios::end);
|
|
327
|
+
current_file_size_ = static_cast<size_t>(log_file_.tellp());
|
|
328
|
+
log_file_.seekp(0, std::ios::end); // Ensure we're at the end for appending
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
void close_log_file() {
|
|
333
|
+
if (log_file_.is_open()) {
|
|
334
|
+
log_file_.close();
|
|
335
|
+
}
|
|
336
|
+
current_file_size_ = 0;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
void rotate_log_files() {
|
|
340
|
+
if (log_file_path_.empty() || max_log_files_ <= 0) return;
|
|
341
|
+
|
|
342
|
+
close_log_file();
|
|
343
|
+
|
|
344
|
+
// Move existing log files
|
|
345
|
+
for (int i = max_log_files_ - 1; i >= 1; i--) {
|
|
346
|
+
std::string old_name = log_file_path_ + "." + std::to_string(i);
|
|
347
|
+
std::string new_name = log_file_path_ + "." + std::to_string(i + 1);
|
|
348
|
+
|
|
349
|
+
// Delete the oldest file if it exists
|
|
350
|
+
if (i == max_log_files_ - 1) {
|
|
351
|
+
std::remove(new_name.c_str());
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Rename old file to new name
|
|
355
|
+
std::rename(old_name.c_str(), new_name.c_str());
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Move current log file to .1
|
|
359
|
+
std::string backup_name = log_file_path_ + ".1";
|
|
360
|
+
std::rename(log_file_path_.c_str(), backup_name.c_str());
|
|
361
|
+
|
|
362
|
+
// Reopen the log file (new empty file)
|
|
363
|
+
open_log_file();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
mutable std::mutex mutex_;
|
|
367
|
+
LogLevel min_level_;
|
|
368
|
+
bool colors_enabled_;
|
|
369
|
+
bool timestamps_enabled_;
|
|
370
|
+
bool is_terminal_;
|
|
371
|
+
|
|
372
|
+
// File logging members
|
|
373
|
+
bool file_logging_enabled_;
|
|
374
|
+
std::string log_file_path_;
|
|
375
|
+
std::ofstream log_file_;
|
|
376
|
+
size_t max_log_file_size_;
|
|
377
|
+
int max_log_files_;
|
|
378
|
+
size_t current_file_size_;
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
} // namespace librats
|
|
382
|
+
|
|
383
|
+
// Convenience macros for easy logging
|
|
384
|
+
#define LOG_DEBUG(module, message) \
|
|
385
|
+
do { \
|
|
386
|
+
std::ostringstream oss; \
|
|
387
|
+
oss << message; \
|
|
388
|
+
librats::Logger::getInstance().log(librats::LogLevel::DEBUG, module, oss.str()); \
|
|
389
|
+
} while(0)
|
|
390
|
+
|
|
391
|
+
#define LOG_INFO(module, message) \
|
|
392
|
+
do { \
|
|
393
|
+
std::ostringstream oss; \
|
|
394
|
+
oss << message; \
|
|
395
|
+
librats::Logger::getInstance().log(librats::LogLevel::INFO, module, oss.str()); \
|
|
396
|
+
} while(0)
|
|
397
|
+
|
|
398
|
+
#define LOG_WARN(module, message) \
|
|
399
|
+
do { \
|
|
400
|
+
std::ostringstream oss; \
|
|
401
|
+
oss << message; \
|
|
402
|
+
librats::Logger::getInstance().log(librats::LogLevel::WARN, module, oss.str()); \
|
|
403
|
+
} while(0)
|
|
404
|
+
|
|
405
|
+
#define LOG_ERROR(module, message) \
|
|
406
|
+
do { \
|
|
407
|
+
std::ostringstream oss; \
|
|
408
|
+
oss << message; \
|
|
409
|
+
librats::Logger::getInstance().log(librats::LogLevel::ERROR, module, oss.str()); \
|
|
410
|
+
} while(0)
|
|
411
|
+
|
|
412
|
+
|