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