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.
Files changed (66) hide show
  1. package/README.md +1 -1
  2. package/binding.gyp +1 -0
  3. package/lib/index.d.ts +2 -1
  4. package/native-src/3rdparty/android/ifaddrs-android.c +600 -0
  5. package/native-src/3rdparty/android/ifaddrs-android.h +54 -0
  6. package/native-src/CMakeLists.txt +360 -0
  7. package/native-src/LICENSE +21 -0
  8. package/native-src/src/bencode.cpp +485 -0
  9. package/native-src/src/bencode.h +145 -0
  10. package/native-src/src/bittorrent.cpp +3682 -0
  11. package/native-src/src/bittorrent.h +731 -0
  12. package/native-src/src/dht.cpp +2460 -0
  13. package/native-src/src/dht.h +508 -0
  14. package/native-src/src/encrypted_socket.cpp +817 -0
  15. package/native-src/src/encrypted_socket.h +239 -0
  16. package/native-src/src/file_transfer.cpp +1808 -0
  17. package/native-src/src/file_transfer.h +567 -0
  18. package/native-src/src/fs.cpp +639 -0
  19. package/native-src/src/fs.h +108 -0
  20. package/native-src/src/gossipsub.cpp +1137 -0
  21. package/native-src/src/gossipsub.h +403 -0
  22. package/native-src/src/ice.cpp +1386 -0
  23. package/native-src/src/ice.h +328 -0
  24. package/native-src/src/json.hpp +25526 -0
  25. package/native-src/src/krpc.cpp +558 -0
  26. package/native-src/src/krpc.h +145 -0
  27. package/native-src/src/librats.cpp +2735 -0
  28. package/native-src/src/librats.h +1732 -0
  29. package/native-src/src/librats_bittorrent.cpp +167 -0
  30. package/native-src/src/librats_c.cpp +1333 -0
  31. package/native-src/src/librats_c.h +239 -0
  32. package/native-src/src/librats_encryption.cpp +123 -0
  33. package/native-src/src/librats_file_transfer.cpp +226 -0
  34. package/native-src/src/librats_gossipsub.cpp +293 -0
  35. package/native-src/src/librats_ice.cpp +515 -0
  36. package/native-src/src/librats_logging.cpp +158 -0
  37. package/native-src/src/librats_mdns.cpp +171 -0
  38. package/native-src/src/librats_nat.cpp +571 -0
  39. package/native-src/src/librats_persistence.cpp +815 -0
  40. package/native-src/src/logger.h +412 -0
  41. package/native-src/src/mdns.cpp +1178 -0
  42. package/native-src/src/mdns.h +253 -0
  43. package/native-src/src/network_utils.cpp +598 -0
  44. package/native-src/src/network_utils.h +162 -0
  45. package/native-src/src/noise.cpp +981 -0
  46. package/native-src/src/noise.h +227 -0
  47. package/native-src/src/os.cpp +371 -0
  48. package/native-src/src/os.h +40 -0
  49. package/native-src/src/rats_export.h +17 -0
  50. package/native-src/src/sha1.cpp +163 -0
  51. package/native-src/src/sha1.h +42 -0
  52. package/native-src/src/socket.cpp +1376 -0
  53. package/native-src/src/socket.h +309 -0
  54. package/native-src/src/stun.cpp +484 -0
  55. package/native-src/src/stun.h +349 -0
  56. package/native-src/src/threadmanager.cpp +105 -0
  57. package/native-src/src/threadmanager.h +53 -0
  58. package/native-src/src/tracker.cpp +1110 -0
  59. package/native-src/src/tracker.h +268 -0
  60. package/native-src/src/version.cpp +24 -0
  61. package/native-src/src/version.h.in +45 -0
  62. package/native-src/version.rc.in +31 -0
  63. package/package.json +2 -8
  64. package/scripts/build-librats.js +59 -12
  65. package/scripts/prepare-package.js +133 -37
  66. package/src/librats_node.cpp +46 -1
@@ -7,36 +7,156 @@ const path = require('path');
7
7
  * Prepare package script
8
8
  *
9
9
  * This script runs before packing and publishing to ensure the package
10
- * is ready for distribution. It checks that all necessary files are present.
10
+ * is ready for distribution. It copies the native C++ source files into
11
+ * the nodejs package directory so they can be included in the npm package.
11
12
  */
12
13
 
13
14
  console.log('Preparing package for distribution...');
14
15
 
15
16
  const projectRoot = path.resolve(__dirname, '..', '..');
16
17
  const nodejsRoot = path.resolve(__dirname, '..');
18
+ const nativeSrcDir = path.join(nodejsRoot, 'native-src');
17
19
 
18
- // Critical files that must be included in the package
20
+ // Helper function to copy a file
21
+ function copyFile(src, dest) {
22
+ const destDir = path.dirname(dest);
23
+ if (!fs.existsSync(destDir)) {
24
+ fs.mkdirSync(destDir, { recursive: true });
25
+ }
26
+ fs.copyFileSync(src, dest);
27
+ }
28
+
29
+ // Helper function to copy a directory recursively
30
+ function copyDir(src, dest, filter = () => true) {
31
+ if (!fs.existsSync(dest)) {
32
+ fs.mkdirSync(dest, { recursive: true });
33
+ }
34
+
35
+ const entries = fs.readdirSync(src, { withFileTypes: true });
36
+ for (const entry of entries) {
37
+ const srcPath = path.join(src, entry.name);
38
+ const destPath = path.join(dest, entry.name);
39
+
40
+ if (entry.isDirectory()) {
41
+ copyDir(srcPath, destPath, filter);
42
+ } else if (filter(entry.name)) {
43
+ copyFile(srcPath, destPath);
44
+ }
45
+ }
46
+ }
47
+
48
+ // Check that we're in the project root with the source files
49
+ if (!fs.existsSync(path.join(projectRoot, 'CMakeLists.txt'))) {
50
+ console.error('\n❌ ERROR: Cannot find CMakeLists.txt in project root.');
51
+ console.error('This script must be run from within the librats repository.');
52
+ console.error(`Expected project root: ${projectRoot}`);
53
+ process.exit(1);
54
+ }
55
+
56
+ if (!fs.existsSync(path.join(projectRoot, 'src'))) {
57
+ console.error('\n❌ ERROR: Cannot find src/ directory in project root.');
58
+ console.error('This script must be run from within the librats repository.');
59
+ process.exit(1);
60
+ }
61
+
62
+ // Clean up existing native-src directory
63
+ if (fs.existsSync(nativeSrcDir)) {
64
+ console.log('Cleaning existing native-src directory...');
65
+ fs.rmSync(nativeSrcDir, { recursive: true, force: true });
66
+ }
67
+
68
+ console.log('\nCopying native source files to native-src/...');
69
+
70
+ // Create native-src directory
71
+ fs.mkdirSync(nativeSrcDir, { recursive: true });
72
+
73
+ // Copy CMakeLists.txt
74
+ console.log(' Copying CMakeLists.txt...');
75
+ copyFile(
76
+ path.join(projectRoot, 'CMakeLists.txt'),
77
+ path.join(nativeSrcDir, 'CMakeLists.txt')
78
+ );
79
+
80
+ // Copy LICENSE
81
+ if (fs.existsSync(path.join(projectRoot, 'LICENSE'))) {
82
+ console.log(' Copying LICENSE...');
83
+ copyFile(
84
+ path.join(projectRoot, 'LICENSE'),
85
+ path.join(nativeSrcDir, 'LICENSE')
86
+ );
87
+ }
88
+
89
+ // Copy version.rc.in
90
+ if (fs.existsSync(path.join(projectRoot, 'version.rc.in'))) {
91
+ console.log(' Copying version.rc.in...');
92
+ copyFile(
93
+ path.join(projectRoot, 'version.rc.in'),
94
+ path.join(nativeSrcDir, 'version.rc.in')
95
+ );
96
+ }
97
+
98
+ // Copy src/ directory (only .cpp, .h, .hpp, .in files, excluding main.cpp)
99
+ console.log(' Copying src/ directory...');
100
+ const srcFilter = (name) => {
101
+ if (name === 'main.cpp') return false;
102
+ return name.endsWith('.cpp') || name.endsWith('.h') ||
103
+ name.endsWith('.hpp') || name.endsWith('.in');
104
+ };
105
+ copyDir(
106
+ path.join(projectRoot, 'src'),
107
+ path.join(nativeSrcDir, 'src'),
108
+ srcFilter
109
+ );
110
+
111
+ // Copy 3rdparty/ directory
112
+ if (fs.existsSync(path.join(projectRoot, '3rdparty'))) {
113
+ console.log(' Copying 3rdparty/ directory...');
114
+ copyDir(
115
+ path.join(projectRoot, '3rdparty'),
116
+ path.join(nativeSrcDir, '3rdparty')
117
+ );
118
+ }
119
+
120
+ // Count copied files
121
+ let cppCount = 0;
122
+ let hCount = 0;
123
+ const countFiles = (dir) => {
124
+ if (!fs.existsSync(dir)) return;
125
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
126
+ for (const entry of entries) {
127
+ const fullPath = path.join(dir, entry.name);
128
+ if (entry.isDirectory()) {
129
+ countFiles(fullPath);
130
+ } else if (entry.name.endsWith('.cpp')) {
131
+ cppCount++;
132
+ } else if (entry.name.endsWith('.h') || entry.name.endsWith('.hpp')) {
133
+ hCount++;
134
+ }
135
+ }
136
+ };
137
+ countFiles(nativeSrcDir);
138
+
139
+ console.log(`\n✓ Copied ${cppCount} source files and ${hCount} header files`);
140
+
141
+ // Verify critical files in nodejs package
19
142
  const criticalFiles = [
20
- // Node.js binding files
21
143
  { path: path.join(nodejsRoot, 'binding.gyp'), desc: 'Node.js binding configuration' },
22
144
  { path: path.join(nodejsRoot, 'lib', 'index.js'), desc: 'JavaScript wrapper' },
23
145
  { path: path.join(nodejsRoot, 'lib', 'index.d.ts'), desc: 'TypeScript definitions' },
24
146
  { path: path.join(nodejsRoot, 'src', 'librats_node.cpp'), desc: 'Node.js binding source' },
25
147
  { path: path.join(nodejsRoot, 'scripts', 'build-librats.js'), desc: 'Build script' },
26
148
  { path: path.join(nodejsRoot, 'scripts', 'postinstall.js'), desc: 'Post-install script' },
27
-
28
- // Librats C++ library files
29
- { path: path.join(projectRoot, 'CMakeLists.txt'), desc: 'CMake configuration' },
30
- { path: path.join(projectRoot, 'src', 'librats.cpp'), desc: 'Librats main source' },
31
- { path: path.join(projectRoot, 'src', 'librats.h'), desc: 'Librats main header' },
32
- { path: path.join(projectRoot, 'src', 'librats_c.cpp'), desc: 'Librats C API' },
33
- { path: path.join(projectRoot, 'src', 'librats_c.h'), desc: 'Librats C API header' },
149
+ { path: path.join(nativeSrcDir, 'CMakeLists.txt'), desc: 'CMake configuration (copied)' },
150
+ { path: path.join(nativeSrcDir, 'src', 'librats.cpp'), desc: 'Librats main source (copied)' },
151
+ { path: path.join(nativeSrcDir, 'src', 'librats.h'), desc: 'Librats main header (copied)' },
152
+ { path: path.join(nativeSrcDir, 'src', 'librats_c.cpp'), desc: 'Librats C API (copied)' },
153
+ { path: path.join(nativeSrcDir, 'src', 'librats_c.h'), desc: 'Librats C API header (copied)' },
34
154
  ];
35
155
 
36
156
  let allFilesPresent = true;
37
157
  let missingFiles = [];
38
158
 
39
- console.log('\nChecking required files:');
159
+ console.log('\nVerifying required files:');
40
160
  for (const file of criticalFiles) {
41
161
  if (fs.existsSync(file.path)) {
42
162
  console.log(` ✓ ${file.desc}`);
@@ -58,34 +178,10 @@ if (!allFilesPresent) {
58
178
  process.exit(1);
59
179
  }
60
180
 
61
- // Check that lib directory exists and has content
62
- const libDir = path.join(nodejsRoot, 'lib');
63
- if (!fs.existsSync(libDir)) {
64
- console.error('\n❌ ERROR: lib directory does not exist!');
65
- console.error('Create it with the JavaScript wrapper and TypeScript definitions.');
66
- process.exit(1);
67
- }
68
-
69
- // Check that scripts directory exists
70
- const scriptsDir = path.join(nodejsRoot, 'scripts');
71
- if (!fs.existsSync(scriptsDir)) {
72
- console.error('\n❌ ERROR: scripts directory does not exist!');
73
- console.error('This directory is required for the build process.');
74
- process.exit(1);
75
- }
76
-
77
- // Count source files
78
- const srcDir = path.join(projectRoot, 'src');
79
- if (fs.existsSync(srcDir)) {
80
- const sourceFiles = fs.readdirSync(srcDir)
81
- .filter(f => f.endsWith('.cpp') || f.endsWith('.h'));
82
- console.log(`\n✓ Found ${sourceFiles.length} source files in src/`);
83
- }
84
-
85
181
  console.log('\n✅ Package is ready for distribution!\n');
86
- console.log('When users install this package via npm:');
182
+ console.log('The native-src/ directory now contains all C++ source files needed to build.');
183
+ console.log('\nWhen users install this package via npm:');
87
184
  console.log(' 1. The preinstall script will build the librats C++ library');
88
185
  console.log(' 2. The install script will build the Node.js native addon');
89
186
  console.log(' 3. The postinstall script will verify the installation');
90
187
  console.log('\nNo manual build steps are required by users!\n');
91
-
@@ -473,7 +473,52 @@ private:
473
473
  std::string content_hash = info[0].As<Napi::String>().Utf8Value();
474
474
  int port = info[1].As<Napi::Number>().Int32Value();
475
475
 
476
- rats_error_t result = rats_announce_for_hash(client_, content_hash.c_str(), port);
476
+ // Check if optional callback is provided
477
+ rats_peers_found_cb c_callback = nullptr;
478
+ void* callback_user_data = nullptr;
479
+ Napi::ThreadSafeFunction* tsfn_ptr = nullptr;
480
+
481
+ if (info.Length() >= 3 && info[2].IsFunction()) {
482
+ // Create thread-safe function for callback
483
+ auto tsfn = new Napi::ThreadSafeFunction();
484
+ *tsfn = Napi::ThreadSafeFunction::New(
485
+ env,
486
+ info[2].As<Napi::Function>(),
487
+ "AnnounceForHashCallback",
488
+ 0,
489
+ 1,
490
+ [](Napi::Env) {} // Release callback
491
+ );
492
+ tsfn_ptr = tsfn;
493
+
494
+ c_callback = [](void* user_data, const char** peer_addresses, int count) {
495
+ auto* tsfn = static_cast<Napi::ThreadSafeFunction*>(user_data);
496
+ if (!tsfn) return;
497
+
498
+ // Copy peer addresses for async callback
499
+ std::vector<std::string>* peers = new std::vector<std::string>();
500
+ for (int i = 0; i < count; i++) {
501
+ if (peer_addresses[i]) {
502
+ peers->push_back(peer_addresses[i]);
503
+ }
504
+ }
505
+
506
+ tsfn->BlockingCall(peers, [](Napi::Env env, Napi::Function jsCallback, std::vector<std::string>* data) {
507
+ Napi::Array arr = Napi::Array::New(env, data->size());
508
+ for (size_t i = 0; i < data->size(); i++) {
509
+ arr.Set(static_cast<uint32_t>(i), Napi::String::New(env, (*data)[i]));
510
+ }
511
+ jsCallback.Call({arr});
512
+ delete data;
513
+ });
514
+
515
+ tsfn->Release();
516
+ delete tsfn;
517
+ };
518
+ callback_user_data = tsfn_ptr;
519
+ }
520
+
521
+ rats_error_t result = rats_announce_for_hash(client_, content_hash.c_str(), port, c_callback, callback_user_data);
477
522
  return Napi::Boolean::New(env, result == RATS_SUCCESS);
478
523
  }
479
524