librats 0.7.2 → 0.9.0

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 (35) hide show
  1. package/README.md +9 -4
  2. package/lib/index.d.ts +9 -22
  3. package/native-src/CMakeLists.txt +132 -50
  4. package/native-src/cmake/ratsConfig.cmake.in +8 -0
  5. package/native-src/src/bt_network.cpp +296 -183
  6. package/native-src/src/bt_network.h +25 -5
  7. package/native-src/src/crypto/sha256.c +1 -1
  8. package/native-src/src/dht.cpp +297 -47
  9. package/native-src/src/dht.h +70 -6
  10. package/native-src/src/file_transfer.cpp +1185 -1578
  11. package/native-src/src/file_transfer.h +240 -521
  12. package/native-src/src/io_poller.cpp +917 -0
  13. package/native-src/src/io_poller.h +138 -0
  14. package/native-src/src/krpc.cpp +161 -96
  15. package/native-src/src/krpc.h +18 -4
  16. package/native-src/src/librats.cpp +812 -1236
  17. package/native-src/src/librats.h +207 -208
  18. package/native-src/src/librats_bittorrent.cpp +1 -5
  19. package/native-src/src/librats_c.cpp +22 -39
  20. package/native-src/src/librats_discovery.cpp +377 -0
  21. package/native-src/src/librats_encryption.cpp +130 -283
  22. package/native-src/src/librats_file_transfer.cpp +27 -109
  23. package/native-src/src/librats_gossipsub.cpp +1 -5
  24. package/native-src/src/librats_ice.cpp +5 -1
  25. package/native-src/src/librats_log_macros.h +36 -0
  26. package/native-src/src/librats_logging.cpp +1 -7
  27. package/native-src/src/librats_mdns.cpp +1 -11
  28. package/native-src/src/librats_persistence.cpp +1 -11
  29. package/native-src/src/librats_reconnection.cpp +2 -13
  30. package/native-src/src/librats_statistic.cpp +105 -0
  31. package/native-src/src/socket.cpp +15 -3
  32. package/package.json +1 -1
  33. package/scripts/build-librats.js +3 -0
  34. package/scripts/prepare-package.js +10 -0
  35. package/src/librats_node.cpp +53 -64
@@ -24,6 +24,7 @@ std::unordered_map<rats_client_t, std::shared_ptr<CallbackData>> binary_callback
24
24
  std::unordered_map<rats_client_t, std::shared_ptr<CallbackData>> json_callbacks;
25
25
  std::unordered_map<rats_client_t, std::shared_ptr<CallbackData>> disconnect_callbacks;
26
26
  std::unordered_map<rats_client_t, std::shared_ptr<CallbackData>> file_progress_callbacks;
27
+ std::unordered_map<rats_client_t, std::shared_ptr<CallbackData>> file_request_callbacks;
27
28
 
28
29
  // C callback wrappers
29
30
  void connection_callback_wrapper(void* user_data, const char* peer_id) {
@@ -95,6 +96,23 @@ void file_progress_callback_wrapper(void* user_data, const char* transfer_id, in
95
96
  }
96
97
  }
97
98
 
99
+ // Fires for every incoming transfer offer (file or directory). The app should
100
+ // respond by calling acceptFileTransfer()/rejectFileTransfer(). remote_path is
101
+ // always empty in the push-only model, so only filename is forwarded.
102
+ void file_request_callback_wrapper(void* user_data, const char* peer_id, const char* transfer_id, const char* remote_path, const char* filename) {
103
+ (void)remote_path;
104
+ rats_client_t client = static_cast<rats_client_t>(user_data);
105
+ auto it = file_request_callbacks.find(client);
106
+ if (it != file_request_callbacks.end() && it->second) {
107
+ auto callback_data = it->second;
108
+ callback_data->callback.Call({
109
+ Napi::String::New(callback_data->env, peer_id),
110
+ Napi::String::New(callback_data->env, transfer_id),
111
+ Napi::String::New(callback_data->env, filename)
112
+ });
113
+ }
114
+ }
115
+
98
116
  class RatsClient : public Napi::ObjectWrap<RatsClient> {
99
117
  public:
100
118
  static Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -178,8 +196,6 @@ public:
178
196
  // File Transfer methods
179
197
  InstanceMethod("sendFile", &RatsClient::SendFile),
180
198
  InstanceMethod("sendDirectory", &RatsClient::SendDirectory),
181
- InstanceMethod("requestFile", &RatsClient::RequestFile),
182
- InstanceMethod("requestDirectory", &RatsClient::RequestDirectory),
183
199
  InstanceMethod("acceptFileTransfer", &RatsClient::AcceptFileTransfer),
184
200
  InstanceMethod("rejectFileTransfer", &RatsClient::RejectFileTransfer),
185
201
  InstanceMethod("cancelFileTransfer", &RatsClient::CancelFileTransfer),
@@ -198,6 +214,7 @@ public:
198
214
  InstanceMethod("onJson", &RatsClient::OnJson),
199
215
  InstanceMethod("onDisconnect", &RatsClient::OnDisconnect),
200
216
  InstanceMethod("onFileProgress", &RatsClient::OnFileProgress),
217
+ InstanceMethod("onFileRequest", &RatsClient::OnFileRequest),
201
218
 
202
219
  // Configuration persistence
203
220
  InstanceMethod("loadConfiguration", &RatsClient::LoadConfiguration),
@@ -240,7 +257,8 @@ public:
240
257
  json_callbacks.erase(client_);
241
258
  disconnect_callbacks.erase(client_);
242
259
  file_progress_callbacks.erase(client_);
243
-
260
+ file_request_callbacks.erase(client_);
261
+
244
262
  rats_destroy(client_);
245
263
  }
246
264
  }
@@ -542,9 +560,10 @@ private:
542
560
  Napi::Value StartMdnsDiscovery(const Napi::CallbackInfo& info) {
543
561
  Napi::Env env = info.Env();
544
562
 
563
+ std::string service;
545
564
  const char* service_name = nullptr;
546
565
  if (info.Length() > 0 && info[0].IsString()) {
547
- std::string service = info[0].As<Napi::String>().Utf8Value();
566
+ service = info[0].As<Napi::String>().Utf8Value();
548
567
  service_name = service.c_str();
549
568
  }
550
569
 
@@ -750,12 +769,13 @@ private:
750
769
  Napi::Value DiscoverPublicAddress(const Napi::CallbackInfo& info) {
751
770
  Napi::Env env = info.Env();
752
771
 
772
+ std::string server_str;
753
773
  const char* server = nullptr;
754
774
  uint16_t port = 0;
755
775
  int timeout_ms = 5000;
756
-
776
+
757
777
  if (info.Length() > 0 && info[0].IsString()) {
758
- std::string server_str = info[0].As<Napi::String>().Utf8Value();
778
+ server_str = info[0].As<Napi::String>().Utf8Value();
759
779
  server = server_str.c_str();
760
780
  }
761
781
  if (info.Length() > 1 && info[1].IsNumber()) {
@@ -976,12 +996,13 @@ private:
976
996
  std::string peer_id = info[0].As<Napi::String>().Utf8Value();
977
997
  std::string file_path = info[1].As<Napi::String>().Utf8Value();
978
998
 
999
+ std::string remote_name;
979
1000
  const char* remote_filename = nullptr;
980
1001
  if (info.Length() > 2 && info[2].IsString()) {
981
- std::string remote_name = info[2].As<Napi::String>().Utf8Value();
1002
+ remote_name = info[2].As<Napi::String>().Utf8Value();
982
1003
  remote_filename = remote_name.c_str();
983
1004
  }
984
-
1005
+
985
1006
  char* transfer_id = rats_send_file(client_, peer_id.c_str(), file_path.c_str(), remote_filename);
986
1007
  if (!transfer_id) return env.Null();
987
1008
 
@@ -1001,63 +1022,15 @@ private:
1001
1022
  std::string peer_id = info[0].As<Napi::String>().Utf8Value();
1002
1023
  std::string directory_path = info[1].As<Napi::String>().Utf8Value();
1003
1024
 
1025
+ std::string remote_name;
1004
1026
  const char* remote_directory_name = nullptr;
1005
1027
  if (info.Length() > 2 && info[2].IsString()) {
1006
- std::string remote_name = info[2].As<Napi::String>().Utf8Value();
1028
+ remote_name = info[2].As<Napi::String>().Utf8Value();
1007
1029
  remote_directory_name = remote_name.c_str();
1008
1030
  }
1009
-
1010
- int recursive = 1;
1011
- if (info.Length() > 3 && info[3].IsBoolean()) {
1012
- recursive = info[3].As<Napi::Boolean>().Value() ? 1 : 0;
1013
- }
1014
-
1015
- char* transfer_id = rats_send_directory(client_, peer_id.c_str(), directory_path.c_str(), remote_directory_name, recursive);
1016
- if (!transfer_id) return env.Null();
1017
-
1018
- Napi::String result = Napi::String::New(env, transfer_id);
1019
- rats_string_free(transfer_id);
1020
- return result;
1021
- }
1022
-
1023
- Napi::Value RequestFile(const Napi::CallbackInfo& info) {
1024
- Napi::Env env = info.Env();
1025
-
1026
- if (info.Length() < 3 || !info[0].IsString() || !info[1].IsString() || !info[2].IsString()) {
1027
- Napi::TypeError::New(env, "Expected peer_id (string), remote_file_path (string), and local_path (string)").ThrowAsJavaScriptException();
1028
- return env.Null();
1029
- }
1030
-
1031
- std::string peer_id = info[0].As<Napi::String>().Utf8Value();
1032
- std::string remote_file_path = info[1].As<Napi::String>().Utf8Value();
1033
- std::string local_path = info[2].As<Napi::String>().Utf8Value();
1034
-
1035
- char* transfer_id = rats_request_file(client_, peer_id.c_str(), remote_file_path.c_str(), local_path.c_str());
1036
- if (!transfer_id) return env.Null();
1037
-
1038
- Napi::String result = Napi::String::New(env, transfer_id);
1039
- rats_string_free(transfer_id);
1040
- return result;
1041
- }
1042
-
1043
- Napi::Value RequestDirectory(const Napi::CallbackInfo& info) {
1044
- Napi::Env env = info.Env();
1045
-
1046
- if (info.Length() < 3 || !info[0].IsString() || !info[1].IsString() || !info[2].IsString()) {
1047
- Napi::TypeError::New(env, "Expected peer_id (string), remote_directory_path (string), and local_directory_path (string)").ThrowAsJavaScriptException();
1048
- return env.Null();
1049
- }
1050
-
1051
- std::string peer_id = info[0].As<Napi::String>().Utf8Value();
1052
- std::string remote_directory_path = info[1].As<Napi::String>().Utf8Value();
1053
- std::string local_directory_path = info[2].As<Napi::String>().Utf8Value();
1054
-
1055
- int recursive = 1;
1056
- if (info.Length() > 3 && info[3].IsBoolean()) {
1057
- recursive = info[3].As<Napi::Boolean>().Value() ? 1 : 0;
1058
- }
1059
-
1060
- char* transfer_id = rats_request_directory(client_, peer_id.c_str(), remote_directory_path.c_str(), local_directory_path.c_str(), recursive);
1031
+
1032
+ // Directory transfers are always recursive; the trailing flag is ignored.
1033
+ char* transfer_id = rats_send_directory(client_, peer_id.c_str(), directory_path.c_str(), remote_directory_name, 1);
1061
1034
  if (!transfer_id) return env.Null();
1062
1035
 
1063
1036
  Napi::String result = Napi::String::New(env, transfer_id);
@@ -1090,12 +1063,13 @@ private:
1090
1063
 
1091
1064
  std::string transfer_id = info[0].As<Napi::String>().Utf8Value();
1092
1065
 
1066
+ std::string reason_str;
1093
1067
  const char* reason = nullptr;
1094
1068
  if (info.Length() > 1 && info[1].IsString()) {
1095
- std::string reason_str = info[1].As<Napi::String>().Utf8Value();
1069
+ reason_str = info[1].As<Napi::String>().Utf8Value();
1096
1070
  reason = reason_str.c_str();
1097
1071
  }
1098
-
1072
+
1099
1073
  rats_error_t result = rats_reject_file_transfer(client_, transfer_id.c_str(), reason);
1100
1074
  return Napi::Boolean::New(env, result == RATS_SUCCESS);
1101
1075
  }
@@ -1271,7 +1245,22 @@ private:
1271
1245
  file_progress_callbacks[client_] = callback_data;
1272
1246
  rats_set_file_progress_callback(client_, file_progress_callback_wrapper, client_);
1273
1247
  }
1274
-
1248
+
1249
+ void OnFileRequest(const Napi::CallbackInfo& info) {
1250
+ Napi::Env env = info.Env();
1251
+
1252
+ if (info.Length() < 1 || !info[0].IsFunction()) {
1253
+ Napi::TypeError::New(env, "Expected callback function").ThrowAsJavaScriptException();
1254
+ return;
1255
+ }
1256
+
1257
+ auto callback_data = std::make_shared<CallbackData>(env);
1258
+ callback_data->callback = Napi::Persistent(info[0].As<Napi::Function>());
1259
+
1260
+ file_request_callbacks[client_] = callback_data;
1261
+ rats_set_file_request_callback(client_, file_request_callback_wrapper, client_);
1262
+ }
1263
+
1275
1264
  // Configuration persistence
1276
1265
  Napi::Value LoadConfiguration(const Napi::CallbackInfo& info) {
1277
1266
  Napi::Env env = info.Env();