@cetapod/react-native-smb 1.0.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 (137) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +72 -0
  3. package/ReactNativeSmb.podspec +59 -0
  4. package/cpp/ios/OnLoad.mm +24 -0
  5. package/cpp/shared/HybridSMB.cpp +324 -0
  6. package/cpp/shared/HybridSMB.hpp +102 -0
  7. package/cpp/shared/ReactNativeSmb.hpp +428 -0
  8. package/cpp/shared/connection/ContextRequest.hpp +27 -0
  9. package/cpp/shared/connection/ContextRequestQueue.cpp +85 -0
  10. package/cpp/shared/connection/ContextRequestQueue.hpp +28 -0
  11. package/cpp/shared/connection/MetadataContextLease.hpp +33 -0
  12. package/cpp/shared/connection/PoolContextHandle.cpp +35 -0
  13. package/cpp/shared/connection/PoolContextHandle.hpp +44 -0
  14. package/cpp/shared/connection/PoolSlot.cpp +73 -0
  15. package/cpp/shared/connection/PoolSlot.hpp +46 -0
  16. package/cpp/shared/connection/PoolTypes.hpp +41 -0
  17. package/cpp/shared/connection/SmbConnection.cpp +385 -0
  18. package/cpp/shared/connection/SmbConnection.hpp +93 -0
  19. package/cpp/shared/connection/SmbConnectionPool.cpp +316 -0
  20. package/cpp/shared/connection/SmbConnectionPool.hpp +84 -0
  21. package/cpp/shared/core/CancellationToken.hpp +22 -0
  22. package/cpp/shared/core/OperatorContext.hpp +24 -0
  23. package/cpp/shared/core/SmbEnums.hpp +126 -0
  24. package/cpp/shared/core/SmbTask.cpp +131 -0
  25. package/cpp/shared/core/SmbTask.hpp +52 -0
  26. package/cpp/shared/core/SmbTaskCore.cpp +222 -0
  27. package/cpp/shared/core/SmbTaskCore.hpp +107 -0
  28. package/cpp/shared/core/SmbTypes.hpp +35 -0
  29. package/cpp/shared/core/TaskObserverHub.cpp +166 -0
  30. package/cpp/shared/core/TaskObserverHub.hpp +66 -0
  31. package/cpp/shared/core/TaskSnapshotCodec.cpp +32 -0
  32. package/cpp/shared/core/TaskSnapshotCodec.hpp +41 -0
  33. package/cpp/shared/io/SmbCopyTree.hpp +114 -0
  34. package/cpp/shared/io/SmbDirScan.hpp +80 -0
  35. package/cpp/shared/io/SmbFileIO.cpp +1355 -0
  36. package/cpp/shared/io/SmbFileIO.hpp +45 -0
  37. package/cpp/shared/io/SmbPathUtil.hpp +75 -0
  38. package/cpp/shared/io/SmbSecurity.cpp +308 -0
  39. package/cpp/shared/io/SmbSecurity.hpp +32 -0
  40. package/cpp/shared/io/SmbTreeOps.hpp +112 -0
  41. package/cpp/shared/operators/Operator.hpp +35 -0
  42. package/cpp/shared/operators/OperatorBase.cpp +57 -0
  43. package/cpp/shared/operators/OperatorBase.hpp +57 -0
  44. package/cpp/shared/operators/connection/ConnectOperator.cpp +19 -0
  45. package/cpp/shared/operators/connection/ConnectOperator.hpp +22 -0
  46. package/cpp/shared/operators/connection/ConnectShareOperator.cpp +19 -0
  47. package/cpp/shared/operators/connection/ConnectShareOperator.hpp +21 -0
  48. package/cpp/shared/operators/connection/DisconnectOperator.cpp +12 -0
  49. package/cpp/shared/operators/connection/DisconnectOperator.hpp +15 -0
  50. package/cpp/shared/operators/connection/InitializeOperator.cpp +12 -0
  51. package/cpp/shared/operators/connection/InitializeOperator.hpp +22 -0
  52. package/cpp/shared/operators/connection/ListSharesOperator.cpp +13 -0
  53. package/cpp/shared/operators/connection/ListSharesOperator.hpp +18 -0
  54. package/cpp/shared/operators/listing/GetPathInfoOperator.cpp +43 -0
  55. package/cpp/shared/operators/listing/GetPathInfoOperator.hpp +21 -0
  56. package/cpp/shared/operators/listing/GetSecurityDescriptorOperator.cpp +202 -0
  57. package/cpp/shared/operators/listing/GetSecurityDescriptorOperator.hpp +22 -0
  58. package/cpp/shared/operators/listing/ListDirectoryOperator.cpp +20 -0
  59. package/cpp/shared/operators/listing/ListDirectoryOperator.hpp +24 -0
  60. package/cpp/shared/operators/mutate/CopyItemOperator.cpp +19 -0
  61. package/cpp/shared/operators/mutate/CopyItemOperator.hpp +25 -0
  62. package/cpp/shared/operators/mutate/CreateDirectoryOperator.cpp +28 -0
  63. package/cpp/shared/operators/mutate/CreateDirectoryOperator.hpp +20 -0
  64. package/cpp/shared/operators/mutate/DeleteItemOperator.cpp +96 -0
  65. package/cpp/shared/operators/mutate/DeleteItemOperator.hpp +23 -0
  66. package/cpp/shared/operators/mutate/DuplicateItemOperator.cpp +48 -0
  67. package/cpp/shared/operators/mutate/DuplicateItemOperator.hpp +23 -0
  68. package/cpp/shared/operators/mutate/MoveItemOperator.cpp +32 -0
  69. package/cpp/shared/operators/mutate/MoveItemOperator.hpp +21 -0
  70. package/cpp/shared/operators/mutate/RenameItemOperator.cpp +37 -0
  71. package/cpp/shared/operators/mutate/RenameItemOperator.hpp +21 -0
  72. package/cpp/shared/operators/transfer/DownloadFileOperator.cpp +31 -0
  73. package/cpp/shared/operators/transfer/DownloadFileOperator.hpp +21 -0
  74. package/cpp/shared/operators/transfer/UploadFileOperator.cpp +27 -0
  75. package/cpp/shared/operators/transfer/UploadFileOperator.hpp +21 -0
  76. package/cpp/shared/util/SmbErrorMapper.hpp +229 -0
  77. package/cpp/shared/util/SmbLog.hpp +20 -0
  78. package/docs/API.md +105 -0
  79. package/docs/ARCHITECTURE.md +70 -0
  80. package/docs/TASK_MODEL.md +149 -0
  81. package/ios/include/smb2/libsmb2-dcerpc-lsa.h +172 -0
  82. package/ios/include/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  83. package/ios/include/smb2/libsmb2-dcerpc.h +155 -0
  84. package/ios/include/smb2/libsmb2-raw.h +497 -0
  85. package/ios/include/smb2/libsmb2.h +1384 -0
  86. package/ios/include/smb2/smb2-errors.h +549 -0
  87. package/ios/include/smb2/smb2.h +1251 -0
  88. package/ios/libs/device/libsmb2-device.a +0 -0
  89. package/ios/libs/libsmb2.xcframework/Info.plist +48 -0
  90. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc-lsa.h +172 -0
  91. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  92. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc.h +155 -0
  93. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-raw.h +497 -0
  94. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2.h +1384 -0
  95. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/smb2-errors.h +549 -0
  96. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/smb2.h +1251 -0
  97. package/ios/libs/libsmb2.xcframework/ios-arm64/libsmb2.a +0 -0
  98. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc-lsa.h +172 -0
  99. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  100. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc.h +155 -0
  101. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-raw.h +497 -0
  102. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2.h +1384 -0
  103. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/smb2-errors.h +549 -0
  104. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/smb2.h +1251 -0
  105. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/libsmb2.a +0 -0
  106. package/ios/libs/simulator/libsmb2-simulator.a +0 -0
  107. package/lib/ReactNativeSmb.d.ts +200 -0
  108. package/lib/ReactNativeSmb.js +1 -0
  109. package/lib/bridge/decode.d.ts +4 -0
  110. package/lib/bridge/decode.js +92 -0
  111. package/lib/core/SMB.d.ts +3 -0
  112. package/lib/core/SMB.js +4 -0
  113. package/lib/core/SmbClient.d.ts +35 -0
  114. package/lib/core/SmbClient.js +99 -0
  115. package/lib/core/SmbTask.d.ts +41 -0
  116. package/lib/core/SmbTask.js +74 -0
  117. package/lib/core/TransferStore.d.ts +22 -0
  118. package/lib/core/TransferStore.js +88 -0
  119. package/lib/core/ids.d.ts +1 -0
  120. package/lib/core/ids.js +3 -0
  121. package/lib/core/taskResult.d.ts +3 -0
  122. package/lib/core/taskResult.js +52 -0
  123. package/lib/hooks/useSubscribe.d.ts +20 -0
  124. package/lib/hooks/useSubscribe.js +36 -0
  125. package/lib/hooks/useTransfers.d.ts +7 -0
  126. package/lib/hooks/useTransfers.js +29 -0
  127. package/lib/index.d.ts +7 -0
  128. package/lib/index.js +7 -0
  129. package/lib/labels.d.ts +6 -0
  130. package/lib/labels.js +71 -0
  131. package/lib/types.d.ts +141 -0
  132. package/lib/types.js +59 -0
  133. package/lib/utils.d.ts +79 -0
  134. package/lib/utils.js +153 -0
  135. package/package.json +63 -0
  136. package/scripts/build-libsmb2.sh +143 -0
  137. package/scripts/create-xcframework.sh +84 -0
@@ -0,0 +1,428 @@
1
+ #include <unordered_map>
2
+ #pragma once
3
+
4
+ #include <NitroModules/HybridObject.hpp>
5
+ #include <NitroModules/JSIConverter.hpp>
6
+ #include <NitroModules/Promise.hpp>
7
+ #include <memory>
8
+ #include <optional>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ #include "core/SmbTask.hpp"
13
+
14
+ namespace react_native_smb {
15
+ using namespace margelo::nitro;
16
+
17
+ using SmbStatusCallback = std::function<void(const std::string&, const std::string&, int)>;
18
+ using SmbProgressCallback = std::function<void(double, double)>;
19
+
20
+ struct SmbCredentials {
21
+ std::string username;
22
+ std::string password;
23
+ };
24
+
25
+ struct SmbShareList {
26
+ std::string name;
27
+ std::string comment;
28
+ };
29
+
30
+ struct SmbConnectionInfo {
31
+ std::string url;
32
+ std::string server;
33
+ std::string share;
34
+ bool isConnected;
35
+ };
36
+
37
+ struct SmbFileInfo {
38
+ std::string name;
39
+ std::string path;
40
+ int64_t size;
41
+ bool isDirectory;
42
+ int64_t modifiedAt; // Content modification time (smb2_mtime)
43
+ int64_t accessedAt; // Last access time (smb2_atime)
44
+ int64_t createdAt; // Creation time (smb2_btime)
45
+ int64_t changedAt; // Attribute change time (smb2_ctime)
46
+ int64_t childCount; // Directories: number of immediate children; -1 if unknown / not a directory
47
+ std::vector<SmbFileInfo> children; // Nested children for directories (when recursive)
48
+ };
49
+
50
+ struct SmbAce {
51
+ std::string aceType; // Type of ACE (e.g., "ACCESS_ALLOWED_ACE",
52
+ // "ACCESS_DENIED_ACE")
53
+ std::vector<std::string> aceFlags; // Flags for the ACE (e.g.,
54
+ // "INHERIT_ONLY", "NO_PROPAGATE_INHERIT")
55
+ std::vector<std::string> mask; // Access mask (e.g., "READ", "WRITE", "EXECUTE")
56
+ std::string sid; // Security Identifier
57
+ };
58
+
59
+ struct SmbAcl {
60
+ uint8_t revision;
61
+ uint16_t aceCount;
62
+ std::vector<SmbAce> aces;
63
+ };
64
+
65
+ struct SmbSecurityDescriptor {
66
+ uint8_t revision;
67
+ std::vector<std::string> control;
68
+ std::string ownerSid;
69
+ std::string groupSid;
70
+ SmbAcl dacl;
71
+ };
72
+
73
+ class ReactNativeSmb : public virtual HybridObject {
74
+ public:
75
+ virtual ~ReactNativeSmb() = default;
76
+
77
+ virtual bool isConnected() = 0;
78
+ virtual bool isInitialized() = 0;
79
+
80
+ // --- Connection Management ---
81
+ virtual std::shared_ptr<SmbTask> initialize(const std::string& taskId, const std::string& url, const SmbCredentials& credentials) = 0;
82
+ virtual std::shared_ptr<SmbTask> connect(const std::string& taskId, const std::string& url, const SmbCredentials& credentials) = 0;
83
+ virtual std::shared_ptr<SmbTask> connectShare(const std::string& taskId, const std::string& share) = 0;
84
+ virtual std::shared_ptr<SmbTask> disconnect(const std::string& taskId) = 0;
85
+ virtual std::shared_ptr<SmbTask> listShares(const std::string& taskId) = 0;
86
+
87
+ // --- Listing & Info ---
88
+ virtual std::shared_ptr<SmbTask> listDirectory(const std::string& taskId, const std::string& path, bool recursive, int maxDepth) = 0;
89
+ virtual std::shared_ptr<SmbTask> getPathInfo(const std::string& taskId, const std::string& path) = 0;
90
+ virtual std::shared_ptr<SmbTask> getSecurityDescriptor(const std::string& taskId, const std::string& path) = 0;
91
+
92
+ // --- File Transfers ---
93
+ virtual std::shared_ptr<SmbTask> downloadFile(const std::string& taskId, const std::string& remotePath, const std::string& localPath) = 0;
94
+ virtual std::shared_ptr<SmbTask> uploadFile(const std::string& taskId, const std::string& localPath, const std::string& remotePath) = 0;
95
+
96
+ // --- Mutating File Operations ---
97
+ virtual std::shared_ptr<SmbTask> createDirectory(const std::string& taskId, const std::string& path) = 0;
98
+ virtual std::shared_ptr<SmbTask> deleteItem(const std::string& taskId, const std::string& path) = 0;
99
+ virtual std::shared_ptr<SmbTask> moveItem(const std::string& taskId, const std::string& fromPath, const std::string& toPath) = 0;
100
+ virtual std::shared_ptr<SmbTask> renameItem(const std::string& taskId, const std::string& currentPath, const std::string& newName) = 0;
101
+ virtual std::shared_ptr<SmbTask> copyItem(const std::string& taskId, const std::string& fromPath, const std::string& toPath, bool recursive) = 0;
102
+ virtual std::shared_ptr<SmbTask> duplicateItem(const std::string& taskId, const std::string& path) = 0;
103
+
104
+ // --- Task control & Task Center APIs ---
105
+ virtual std::string subscribeTaskEvents(const std::function<void(const std::unordered_map<std::string, std::string>&)>& listener) = 0;
106
+ virtual void unsubscribeTaskEvents(const std::string& subscriptionId) = 0;
107
+ virtual std::unordered_map<std::string, std::string> getTask(const std::string& taskId) = 0;
108
+ virtual std::vector<std::unordered_map<std::string, std::string>> getActiveTasks() = 0;
109
+ virtual std::vector<std::unordered_map<std::string, std::string>> getTaskHistory(int limit, int offset) = 0;
110
+ virtual void cancelTask(const std::string& taskId) = 0;
111
+ virtual void clearTaskHistory(int64_t beforeTs) = 0;
112
+
113
+ // Debug / instrumentation
114
+ virtual std::string subscribePoolInfo(const std::function<void(const std::vector<std::unordered_map<std::string, std::string>>&)>& listener) = 0;
115
+ virtual void unsubscribePoolInfo(const std::string& subscriptionId) = 0;
116
+ virtual std::vector<std::unordered_map<std::string, std::string>> getPoolInfo() = 0;
117
+ virtual void resetPool() = 0;
118
+
119
+ protected:
120
+ static constexpr auto NAME = "ReactNativeSmb";
121
+ };
122
+
123
+ } // namespace react_native_smb
124
+
125
+ namespace margelo::nitro {
126
+ using namespace react_native_smb;
127
+
128
+ template <>
129
+ struct JSIConverter<SmbCredentials> {
130
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbCredentials& credentials) {
131
+ jsi::Object obj(runtime);
132
+ obj.setProperty(runtime, "username", jsi::String::createFromUtf8(runtime, credentials.username));
133
+ obj.setProperty(runtime, "password", jsi::String::createFromUtf8(runtime, credentials.password));
134
+ return obj;
135
+ }
136
+
137
+ static SmbCredentials fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
138
+ if (!value.isObject()) {
139
+ throw std::invalid_argument("SmbCredentials must be an object");
140
+ }
141
+
142
+ jsi::Object obj = value.asObject(runtime);
143
+ SmbCredentials credentials;
144
+
145
+ credentials.username = obj.getProperty(runtime, "username").asString(runtime).utf8(runtime);
146
+ credentials.password = obj.getProperty(runtime, "password").asString(runtime).utf8(runtime);
147
+
148
+ return credentials;
149
+ }
150
+
151
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
152
+ };
153
+
154
+ template <>
155
+ struct JSIConverter<SmbConnectionInfo> {
156
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbConnectionInfo& connection) {
157
+ jsi::Object obj(runtime);
158
+ obj.setProperty(runtime, "url", jsi::String::createFromUtf8(runtime, connection.url));
159
+ obj.setProperty(runtime, "server", jsi::String::createFromUtf8(runtime, connection.server));
160
+ obj.setProperty(runtime, "share", jsi::String::createFromUtf8(runtime, connection.share));
161
+ obj.setProperty(runtime, "isConnected", jsi::Value(connection.isConnected));
162
+ return obj;
163
+ }
164
+
165
+ static SmbConnectionInfo fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
166
+ if (!value.isObject()) {
167
+ throw std::invalid_argument("SmbConnectionInfo must be an object");
168
+ }
169
+
170
+ jsi::Object obj = value.asObject(runtime);
171
+ return SmbConnectionInfo{obj.getProperty(runtime, "url").asString(runtime).utf8(runtime), obj.getProperty(runtime, "server").asString(runtime).utf8(runtime),
172
+ obj.getProperty(runtime, "share").asString(runtime).utf8(runtime), obj.getProperty(runtime, "isConnected").asBool()};
173
+ }
174
+
175
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
176
+ };
177
+
178
+ template <>
179
+ struct JSIConverter<SmbFileInfo> {
180
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbFileInfo& fileInfo) {
181
+ jsi::Object obj(runtime);
182
+ obj.setProperty(runtime, "name", jsi::String::createFromUtf8(runtime, fileInfo.name));
183
+ obj.setProperty(runtime, "path", jsi::String::createFromUtf8(runtime, fileInfo.path));
184
+ obj.setProperty(runtime, "size", jsi::Value(static_cast<double>(fileInfo.size)));
185
+ obj.setProperty(runtime, "isDirectory", jsi::Value(fileInfo.isDirectory));
186
+ obj.setProperty(runtime, "modifiedAt", jsi::Value(static_cast<double>(fileInfo.modifiedAt)));
187
+ obj.setProperty(runtime, "accessedAt", jsi::Value(static_cast<double>(fileInfo.accessedAt)));
188
+ obj.setProperty(runtime, "createdAt", jsi::Value(static_cast<double>(fileInfo.createdAt)));
189
+ obj.setProperty(runtime, "changedAt", jsi::Value(static_cast<double>(fileInfo.changedAt)));
190
+ obj.setProperty(runtime, "childCount", jsi::Value(static_cast<double>(fileInfo.childCount)));
191
+
192
+ jsi::Array childrenArray(runtime, fileInfo.children.size());
193
+ for (size_t i = 0; i < fileInfo.children.size(); i++) {
194
+ childrenArray.setValueAtIndex(runtime, i, toJSI(runtime, fileInfo.children[i]));
195
+ }
196
+ obj.setProperty(runtime, "children", std::move(childrenArray));
197
+
198
+ return obj;
199
+ }
200
+
201
+ static SmbFileInfo fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
202
+ if (!value.isObject()) {
203
+ throw std::invalid_argument("SmbFileInfo must be an object");
204
+ }
205
+
206
+ jsi::Object obj = value.asObject(runtime);
207
+
208
+ std::vector<SmbFileInfo> children;
209
+ if (obj.hasProperty(runtime, "children")) {
210
+ jsi::Value childrenValue = obj.getProperty(runtime, "children");
211
+ if (childrenValue.isObject() && childrenValue.asObject(runtime).isArray(runtime)) {
212
+ jsi::Array childrenArray = childrenValue.asObject(runtime).asArray(runtime);
213
+ size_t childrenCount = childrenArray.size(runtime);
214
+ children.reserve(childrenCount);
215
+
216
+ for (size_t i = 0; i < childrenCount; i++) {
217
+ jsi::Value childValue = childrenArray.getValueAtIndex(runtime, i);
218
+ children.push_back(fromJSI(runtime, childValue));
219
+ }
220
+ }
221
+ }
222
+
223
+ return SmbFileInfo{obj.getProperty(runtime, "name").asString(runtime).utf8(runtime),
224
+ obj.getProperty(runtime, "path").asString(runtime).utf8(runtime),
225
+ static_cast<int64_t>(obj.getProperty(runtime, "size").asNumber()),
226
+ obj.getProperty(runtime, "isDirectory").asBool(),
227
+ static_cast<int64_t>(obj.getProperty(runtime, "modifiedAt").asNumber()),
228
+ static_cast<int64_t>(obj.hasProperty(runtime, "accessedAt") ? obj.getProperty(runtime, "accessedAt").asNumber() : 0),
229
+ static_cast<int64_t>(obj.hasProperty(runtime, "createdAt") ? obj.getProperty(runtime, "createdAt").asNumber() : 0),
230
+ static_cast<int64_t>(obj.hasProperty(runtime, "changedAt") ? obj.getProperty(runtime, "changedAt").asNumber() : 0),
231
+ static_cast<int64_t>(obj.hasProperty(runtime, "childCount") ? obj.getProperty(runtime, "childCount").asNumber() : -1),
232
+ children};
233
+ }
234
+
235
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
236
+ };
237
+
238
+ template <>
239
+ struct JSIConverter<SmbShareList> {
240
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbShareList& share) {
241
+ jsi::Object obj(runtime);
242
+ obj.setProperty(runtime, "name", jsi::String::createFromUtf8(runtime, share.name));
243
+ obj.setProperty(runtime, "comment", jsi::String::createFromUtf8(runtime, share.comment));
244
+ return obj;
245
+ }
246
+
247
+ static SmbShareList fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
248
+ if (!value.isObject()) {
249
+ throw std::invalid_argument("SmbShareList must be an object");
250
+ }
251
+
252
+ jsi::Object obj = value.asObject(runtime);
253
+ return SmbShareList{obj.getProperty(runtime, "name").asString(runtime).utf8(runtime), obj.getProperty(runtime, "comment").asString(runtime).utf8(runtime)};
254
+ }
255
+
256
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
257
+ };
258
+
259
+ template <>
260
+ struct JSIConverter<SmbAce> {
261
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbAce& ace) {
262
+ jsi::Object obj(runtime);
263
+ obj.setProperty(runtime, "aceType", jsi::String::createFromUtf8(runtime, ace.aceType));
264
+
265
+ jsi::Array aceFlagsArray = jsi::Array(runtime, ace.aceFlags.size());
266
+ for (size_t i = 0; i < ace.aceFlags.size(); i++) {
267
+ aceFlagsArray.setValueAtIndex(runtime, i, jsi::String::createFromUtf8(runtime, ace.aceFlags[i]));
268
+ }
269
+ obj.setProperty(runtime, "aceFlags", aceFlagsArray);
270
+
271
+ jsi::Array maskArray = jsi::Array(runtime, ace.mask.size());
272
+ for (size_t i = 0; i < ace.mask.size(); i++) {
273
+ maskArray.setValueAtIndex(runtime, i, jsi::String::createFromUtf8(runtime, ace.mask[i]));
274
+ }
275
+ obj.setProperty(runtime, "mask", maskArray);
276
+
277
+ obj.setProperty(runtime, "sid", jsi::String::createFromUtf8(runtime, ace.sid));
278
+ return obj;
279
+ }
280
+
281
+ static SmbAce fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
282
+ if (!value.isObject()) {
283
+ throw std::invalid_argument("SmbAce must be an object");
284
+ }
285
+
286
+ jsi::Object obj = value.asObject(runtime);
287
+ SmbAce ace;
288
+
289
+ ace.aceType = obj.getProperty(runtime, "aceType").asString(runtime).utf8(runtime);
290
+
291
+ if (obj.hasProperty(runtime, "aceFlags")) {
292
+ jsi::Value aceFlagsValue = obj.getProperty(runtime, "aceFlags");
293
+ if (aceFlagsValue.isObject() && aceFlagsValue.asObject(runtime).isArray(runtime)) {
294
+ jsi::Array aceFlagsArray = aceFlagsValue.asObject(runtime).asArray(runtime);
295
+ size_t flagsCount = aceFlagsArray.size(runtime);
296
+ ace.aceFlags.reserve(flagsCount);
297
+
298
+ for (size_t i = 0; i < flagsCount; i++) {
299
+ jsi::Value flagItem = aceFlagsArray.getValueAtIndex(runtime, i);
300
+ if (flagItem.isString()) {
301
+ ace.aceFlags.push_back(flagItem.asString(runtime).utf8(runtime));
302
+ }
303
+ }
304
+ }
305
+ }
306
+
307
+ if (obj.hasProperty(runtime, "mask")) {
308
+ jsi::Value maskValue = obj.getProperty(runtime, "mask");
309
+ if (maskValue.isObject() && maskValue.asObject(runtime).isArray(runtime)) {
310
+ jsi::Array maskArray = maskValue.asObject(runtime).asArray(runtime);
311
+ size_t maskCount = maskArray.size(runtime);
312
+ ace.mask.reserve(maskCount);
313
+
314
+ for (size_t i = 0; i < maskCount; i++) {
315
+ jsi::Value maskItem = maskArray.getValueAtIndex(runtime, i);
316
+ if (maskItem.isString()) {
317
+ ace.mask.push_back(maskItem.asString(runtime).utf8(runtime));
318
+ }
319
+ }
320
+ }
321
+ }
322
+
323
+ ace.sid = obj.getProperty(runtime, "sid").asString(runtime).utf8(runtime);
324
+
325
+ return ace;
326
+ }
327
+
328
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
329
+ };
330
+
331
+ template <>
332
+ struct JSIConverter<SmbAcl> {
333
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbAcl& acl) {
334
+ jsi::Object obj(runtime);
335
+ obj.setProperty(runtime, "revision", jsi::Value(static_cast<double>(acl.revision)));
336
+ obj.setProperty(runtime, "aceCount", jsi::Value(static_cast<double>(acl.aceCount)));
337
+
338
+ jsi::Array aces = jsi::Array(runtime, acl.aces.size());
339
+ for (size_t i = 0; i < acl.aces.size(); i++) {
340
+ aces.setValueAtIndex(runtime, i, JSIConverter<SmbAce>::toJSI(runtime, acl.aces[i]));
341
+ }
342
+ obj.setProperty(runtime, "aces", aces);
343
+
344
+ return obj;
345
+ }
346
+
347
+ static SmbAcl fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
348
+ if (!value.isObject()) {
349
+ throw std::invalid_argument("SmbAcl must be an object");
350
+ }
351
+
352
+ jsi::Object obj = value.asObject(runtime);
353
+ SmbAcl acl;
354
+ acl.revision = static_cast<uint8_t>(obj.getProperty(runtime, "revision").asNumber());
355
+ acl.aceCount = static_cast<uint16_t>(obj.getProperty(runtime, "aceCount").asNumber());
356
+
357
+ if (obj.hasProperty(runtime, "aces")) {
358
+ jsi::Array aces = obj.getProperty(runtime, "aces").asObject(runtime).asArray(runtime);
359
+ size_t aceCount = aces.size(runtime);
360
+ acl.aces.reserve(aceCount);
361
+
362
+ for (size_t i = 0; i < aceCount; i++) {
363
+ jsi::Value aceValue = aces.getValueAtIndex(runtime, i);
364
+ acl.aces.push_back(JSIConverter<SmbAce>::fromJSI(runtime, aceValue));
365
+ }
366
+ }
367
+
368
+ return acl;
369
+ }
370
+
371
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
372
+ };
373
+
374
+ template <>
375
+ struct JSIConverter<SmbSecurityDescriptor> {
376
+ static jsi::Value toJSI(jsi::Runtime& runtime, const SmbSecurityDescriptor& sd) {
377
+ jsi::Object obj(runtime);
378
+ obj.setProperty(runtime, "revision", jsi::Value(static_cast<double>(sd.revision)));
379
+
380
+ jsi::Array controlArray = jsi::Array(runtime, sd.control.size());
381
+ for (size_t i = 0; i < sd.control.size(); i++) {
382
+ controlArray.setValueAtIndex(runtime, i, jsi::String::createFromUtf8(runtime, sd.control[i]));
383
+ }
384
+ obj.setProperty(runtime, "control", controlArray);
385
+
386
+ obj.setProperty(runtime, "ownerSid", jsi::String::createFromUtf8(runtime, sd.ownerSid));
387
+ obj.setProperty(runtime, "groupSid", jsi::String::createFromUtf8(runtime, sd.groupSid));
388
+ obj.setProperty(runtime, "dacl", JSIConverter<SmbAcl>::toJSI(runtime, sd.dacl));
389
+ return obj;
390
+ }
391
+
392
+ static SmbSecurityDescriptor fromJSI(jsi::Runtime& runtime, const jsi::Value& value) {
393
+ if (!value.isObject()) {
394
+ throw std::invalid_argument("SmbSecurityDescriptor must be an object");
395
+ }
396
+
397
+ jsi::Object obj = value.asObject(runtime);
398
+ SmbSecurityDescriptor sd;
399
+
400
+ sd.revision = static_cast<uint8_t>(obj.getProperty(runtime, "revision").asNumber());
401
+
402
+ if (obj.hasProperty(runtime, "control")) {
403
+ jsi::Value controlValue = obj.getProperty(runtime, "control");
404
+ if (controlValue.isObject() && controlValue.asObject(runtime).isArray(runtime)) {
405
+ jsi::Array controlArray = controlValue.asObject(runtime).asArray(runtime);
406
+ size_t controlCount = controlArray.size(runtime);
407
+ sd.control.reserve(controlCount);
408
+
409
+ for (size_t i = 0; i < controlCount; i++) {
410
+ jsi::Value controlItem = controlArray.getValueAtIndex(runtime, i);
411
+ if (controlItem.isString()) {
412
+ sd.control.push_back(controlItem.asString(runtime).utf8(runtime));
413
+ }
414
+ }
415
+ }
416
+ }
417
+
418
+ sd.ownerSid = obj.getProperty(runtime, "ownerSid").asString(runtime).utf8(runtime);
419
+ sd.groupSid = obj.getProperty(runtime, "groupSid").asString(runtime).utf8(runtime);
420
+ sd.dacl = JSIConverter<SmbAcl>::fromJSI(runtime, obj.getProperty(runtime, "dacl"));
421
+
422
+ return sd;
423
+ }
424
+
425
+ static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { return value.isObject(); }
426
+ };
427
+
428
+ } // namespace margelo::nitro
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include <atomic>
4
+ #include <cstdint>
5
+ #include <future>
6
+ #include <memory>
7
+ #include <string>
8
+
9
+ #include "PoolTypes.hpp"
10
+
11
+ namespace react_native_smb {
12
+
13
+ class PoolContextHandle;
14
+
15
+ struct ContextRequest {
16
+ uint64_t id{0};
17
+ AcquireMode mode{AcquireMode::Interactive};
18
+ SmbOperatorKind kind{SmbOperatorKind::Initialize};
19
+ std::string taskId;
20
+ std::promise<PoolContextHandle> promise;
21
+ std::atomic<bool> cancelled{false};
22
+ std::atomic<bool> fulfilled{false};
23
+ };
24
+
25
+ using ContextRequestPtr = std::shared_ptr<ContextRequest>;
26
+
27
+ } // namespace react_native_smb
@@ -0,0 +1,85 @@
1
+ #include "ContextRequestQueue.hpp"
2
+
3
+ #include "PoolContextHandle.hpp"
4
+ #include "../core/SmbEnums.hpp"
5
+
6
+ namespace react_native_smb {
7
+
8
+ size_t ContextRequestQueue::pendingCount() const {
9
+ return interactivePending_.size() + metadataPending_.size();
10
+ }
11
+
12
+ void ContextRequestQueue::drainCancelledFromHead(std::deque<ContextRequestPtr>& queue) {
13
+ while (!queue.empty()) {
14
+ auto& front = queue.front();
15
+ if (!front->cancelled.load(std::memory_order_acquire)) break;
16
+ if (!front->fulfilled.load(std::memory_order_acquire)) {
17
+ front->fulfilled.store(true, std::memory_order_release);
18
+ try {
19
+ front->promise.set_value(PoolContextHandle{});
20
+ } catch (...) {
21
+ }
22
+ }
23
+ queue.pop_front();
24
+ }
25
+ }
26
+
27
+ ContextRequestPtr ContextRequestQueue::enqueue(AcquireMode mode, SmbOperatorKind kind, const std::string& taskId) {
28
+ auto req = std::make_shared<ContextRequest>();
29
+ req->id = nextId_++;
30
+ req->mode = mode;
31
+ req->kind = kind;
32
+ req->taskId = taskId;
33
+
34
+ auto& queue = (mode == AcquireMode::Interactive) ? interactivePending_ : metadataPending_;
35
+ queue.push_back(req);
36
+ return req;
37
+ }
38
+
39
+ ContextRequestPtr ContextRequestQueue::takeNext() {
40
+ drainCancelledFromHead(interactivePending_);
41
+ if (!interactivePending_.empty()) {
42
+ ContextRequestPtr out = std::move(interactivePending_.front());
43
+ interactivePending_.pop_front();
44
+ return out;
45
+ }
46
+
47
+ drainCancelledFromHead(metadataPending_);
48
+ if (!metadataPending_.empty()) {
49
+ ContextRequestPtr out = std::move(metadataPending_.front());
50
+ metadataPending_.pop_front();
51
+ return out;
52
+ }
53
+
54
+ return nullptr;
55
+ }
56
+
57
+ void ContextRequestQueue::requeueFront(ContextRequestPtr req) {
58
+ if (!req) return;
59
+ auto& queue = (req->mode == AcquireMode::Interactive) ? interactivePending_ : metadataPending_;
60
+ queue.push_front(std::move(req));
61
+ }
62
+
63
+ void ContextRequestQueue::cancelForTask(const std::string& taskId) {
64
+ auto cancelIn = [&](std::deque<ContextRequestPtr>& queue) {
65
+ for (auto& req : queue) {
66
+ if (req->taskId != taskId) continue;
67
+ if (req->fulfilled.load(std::memory_order_acquire)) continue;
68
+ req->cancelled.store(true, std::memory_order_release);
69
+ req->fulfilled.store(true, std::memory_order_release);
70
+ try {
71
+ req->promise.set_value(PoolContextHandle{});
72
+ } catch (...) {
73
+ }
74
+ }
75
+ };
76
+ cancelIn(interactivePending_);
77
+ cancelIn(metadataPending_);
78
+ }
79
+
80
+ void ContextRequestQueue::removeCancelledFromHead() {
81
+ drainCancelledFromHead(interactivePending_);
82
+ drainCancelledFromHead(metadataPending_);
83
+ }
84
+
85
+ } // namespace react_native_smb
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include <cstdint>
4
+ #include <deque>
5
+ #include <memory>
6
+
7
+ #include "ContextRequest.hpp"
8
+
9
+ namespace react_native_smb {
10
+
11
+ class ContextRequestQueue {
12
+ public:
13
+ ContextRequestPtr enqueue(AcquireMode mode, SmbOperatorKind kind, const std::string& taskId);
14
+ ContextRequestPtr takeNext();
15
+ void requeueFront(ContextRequestPtr req);
16
+ void removeCancelledFromHead();
17
+ void cancelForTask(const std::string& taskId);
18
+
19
+ private:
20
+ size_t pendingCount() const;
21
+ void drainCancelledFromHead(std::deque<ContextRequestPtr>& queue);
22
+
23
+ std::deque<ContextRequestPtr> interactivePending_;
24
+ std::deque<ContextRequestPtr> metadataPending_;
25
+ uint64_t nextId_{1};
26
+ };
27
+
28
+ } // namespace react_native_smb
@@ -0,0 +1,33 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <utility>
5
+
6
+ #include "../core/SmbEnums.hpp"
7
+ #include "PoolContextHandle.hpp"
8
+ #include "PoolTypes.hpp"
9
+ #include "SmbConnectionPool.hpp"
10
+
11
+ namespace react_native_smb {
12
+
13
+ // Holds one metadata pool slot for multiple submitSync calls (e.g. entire copyTreeImpl).
14
+ class MetadataContextLease {
15
+ public:
16
+ MetadataContextLease(SmbConnectionPool& pool, SmbOperatorKind kind, const std::string& taskId)
17
+ : handle_(pool.requestContext(AcquireMode::Metadata, kind, taskId)) {}
18
+
19
+ MetadataContextLease(MetadataContextLease&&) = default;
20
+ MetadataContextLease& operator=(MetadataContextLease&&) = default;
21
+ MetadataContextLease(const MetadataContextLease&) = delete;
22
+ MetadataContextLease& operator=(const MetadataContextLease&) = delete;
23
+
24
+ template <typename Fn>
25
+ auto submitSync(Fn&& fn) {
26
+ return handle_.submitSync(std::forward<Fn>(fn));
27
+ }
28
+
29
+ private:
30
+ PoolContextHandle handle_;
31
+ };
32
+
33
+ } // namespace react_native_smb
@@ -0,0 +1,35 @@
1
+ #include "PoolContextHandle.hpp"
2
+
3
+ #include "SmbConnectionPool.hpp"
4
+
5
+ namespace react_native_smb {
6
+
7
+ PoolContextHandle::PoolContextHandle(SmbConnectionPool* pool, size_t idx, SmbConnectionManager* conn)
8
+ : pool_(pool), slotIndex_(idx), conn_(conn) {}
9
+
10
+ PoolContextHandle::~PoolContextHandle() {
11
+ if (pool_ && conn_) pool_->releaseContext(*this);
12
+ }
13
+
14
+ PoolContextHandle::PoolContextHandle(PoolContextHandle&& o) noexcept : pool_(o.pool_), slotIndex_(o.slotIndex_), conn_(o.conn_) {
15
+ o.pool_ = nullptr;
16
+ o.conn_ = nullptr;
17
+ }
18
+
19
+ PoolContextHandle& PoolContextHandle::operator=(PoolContextHandle&& o) noexcept {
20
+ if (this != &o) {
21
+ if (pool_ && conn_) pool_->releaseContext(*this);
22
+ pool_ = o.pool_;
23
+ slotIndex_ = o.slotIndex_;
24
+ conn_ = o.conn_;
25
+ o.pool_ = nullptr;
26
+ o.conn_ = nullptr;
27
+ }
28
+ return *this;
29
+ }
30
+
31
+ SmbConnectionManager& PoolContextHandle::manager() const { return *conn_; }
32
+
33
+ smb2_context* PoolContextHandle::ctx() const { return conn_->rawCtx(); }
34
+
35
+ } // namespace react_native_smb
@@ -0,0 +1,44 @@
1
+ #pragma once
2
+
3
+ #include <cstddef>
4
+ #include <ctime>
5
+ #include <type_traits>
6
+ #include <utility>
7
+
8
+ #include <smb2/smb2.h>
9
+
10
+ #include "SmbConnection.hpp"
11
+
12
+ namespace react_native_smb {
13
+
14
+ class SmbConnectionPool;
15
+
16
+ class PoolContextHandle {
17
+ public:
18
+ PoolContextHandle() = default;
19
+ PoolContextHandle(SmbConnectionPool* pool, size_t idx, SmbConnectionManager* conn);
20
+ ~PoolContextHandle();
21
+
22
+ PoolContextHandle(PoolContextHandle&& o) noexcept;
23
+ PoolContextHandle& operator=(PoolContextHandle&& o) noexcept;
24
+ PoolContextHandle(const PoolContextHandle&) = delete;
25
+ PoolContextHandle& operator=(const PoolContextHandle&) = delete;
26
+
27
+ bool valid() const { return conn_ != nullptr; }
28
+ size_t slotIndex() const { return slotIndex_; }
29
+
30
+ SmbConnectionManager& manager() const;
31
+ smb2_context* ctx() const;
32
+
33
+ template <typename Fn, typename R = std::invoke_result_t<Fn, smb2_context*>>
34
+ R submitSync(Fn&& fn) {
35
+ return conn_->submitSync(std::forward<Fn>(fn));
36
+ }
37
+
38
+ private:
39
+ SmbConnectionPool* pool_{nullptr};
40
+ size_t slotIndex_{0};
41
+ SmbConnectionManager* conn_{nullptr};
42
+ };
43
+
44
+ } // namespace react_native_smb