-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathreact-native-fast-rsa.cpp
161 lines (132 loc) · 6.15 KB
/
react-native-fast-rsa.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#import "react-native-fast-rsa.h"
#include <cstdlib>
#include <cstring>
#include <future>
#include <iostream>
#include <sstream>
#include <future>
#include <thread>
#include "librsa_bridge.h"
using namespace facebook;
namespace fastRSA {
jsi::Value call(jsi::Runtime &runtime, const jsi::String &nameValue,
const jsi::Object &payloadObject) {
// Extract and validate name
std::string nameString = nameValue.utf8(runtime);
if (nameString.empty()) {
throw jsi::JSError(runtime, "Name string cannot be empty");
}
// Create a mutable copy of the name string
std::vector<char> mutableName(nameString.begin(), nameString.end());
mutableName.push_back('\0'); // Ensure null termination
// Extract and validate payload
if (!payloadObject.isArrayBuffer(runtime)) {
throw jsi::JSError(runtime, "Payload must be an ArrayBuffer");
}
jsi::ArrayBuffer payload = payloadObject.getArrayBuffer(runtime);
int size = static_cast<int>(payload.length(runtime));
const uint8_t *data = payload.data(runtime);
// Cast const uint8_t* to void*
void *dataPointer = const_cast<void *>(static_cast<const void *>(data));
// Call the RSA bridge
auto response = RSABridgeCall(mutableName.data(), dataPointer, size);
// Handle errors from the bridge
if (response->error != nullptr) {
std::string errorMessage(response->error);
free(response);
throw jsi::JSError(runtime, errorMessage);
}
// Create and populate the ArrayBuffer result
auto arrayBufferConstructor = runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer");
jsi::Object result = arrayBufferConstructor.callAsConstructor(runtime, response->size).getObject(runtime);
jsi::ArrayBuffer resultBuffer = result.getArrayBuffer(runtime);
memcpy(resultBuffer.data(runtime), response->message, response->size);
// Clean up and return the result
free(response);
return result;
}
void install(jsi::Runtime &jsiRuntime) {
std::cout << "Initializing react-native-fast-rsa" << "\n";
auto bridgeCallSync = jsi::Function::createFromHostFunction(
jsiRuntime,
jsi::PropNameID::forAscii(jsiRuntime, "callSync"),
2,
[](jsi::Runtime &runtime, const jsi::Value & /*thisValue*/, const jsi::Value *arguments, size_t count) -> jsi::Value {
// Validate argument count
if (count != 2) {
throw jsi::JSError(runtime, "callSync expects exactly 2 arguments: (string name, ArrayBuffer payload)");
}
// Validate first argument: name (string)
if (!arguments[0].isString()) {
throw jsi::JSError(runtime, "First argument must be a string representing the name");
}
auto nameString = arguments[0].getString(runtime);
// Validate second argument: payload (ArrayBuffer)
if (!arguments[1].isObject() || !arguments[1].getObject(runtime).isArrayBuffer(runtime)) {
throw jsi::JSError(runtime, "Second argument must be an ArrayBuffer representing the payload");
}
auto payloadObject = arguments[1].getObject(runtime);
// Call the native function
auto response = call(runtime, nameString, payloadObject);
// Return the response (could be either an error or result)
return response;
});
auto bridgeCallPromise = jsi::Function::createFromHostFunction(
jsiRuntime,
jsi::PropNameID::forAscii(jsiRuntime, "callPromise"),
2,
[](jsi::Runtime &runtime, const jsi::Value & /*thisValue*/, const jsi::Value *arguments,
size_t count) -> jsi::Value {
// Validate argument count
if (count != 2) {
throw jsi::JSError(runtime, "callPromise expects exactly 2 arguments: (string name, ArrayBuffer payload)");
}
// Validate and extract 'name' argument
if (!arguments[0].isString()) {
throw jsi::JSError(runtime, "First argument must be a string representing the name");
}
auto name = arguments[0].getString(runtime);
// Validate and extract 'payload' argument
if (!arguments[1].isObject() || !arguments[1].getObject(runtime).isArrayBuffer(runtime)) {
throw jsi::JSError(runtime, "Second argument must be an ArrayBuffer representing the payload");
}
auto payload = arguments[1].getObject(runtime).getArrayBuffer(runtime);
// Create shared pointers for name and payload
auto namePtr = std::make_shared<jsi::String>(std::move(name));
auto payloadPtr = std::make_shared<jsi::ArrayBuffer>(std::move(payload));
// Create the Promise executor function
auto promiseExecutor = jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forAscii(runtime, "executor"),
2,
[namePtr, payloadPtr](
jsi::Runtime &runtime,
const jsi::Value & /*thisValue*/,
const jsi::Value *executorArgs,
size_t executorArgCount) -> jsi::Value {
if (executorArgCount != 2) {
throw jsi::JSError(runtime, "Executor function expects exactly 2 arguments: (resolve, reject)");
}
auto resolve = executorArgs[0].asObject(runtime).asFunction(runtime);
auto reject = executorArgs[1].asObject(runtime).asFunction(runtime);
try {
auto response = call(runtime, *namePtr, *payloadPtr);
resolve.call(runtime, response);
} catch (const jsi::JSError &error) {
reject.call(runtime, error.value());
} catch (const std::exception &e) {
reject.call(runtime, jsi::String::createFromUtf8(runtime, e.what()));
}
return jsi::Value::undefined();
});
// Construct and return the Promise
auto promiseConstructor = runtime.global().getPropertyAsFunction(runtime, "Promise");
auto promise = promiseConstructor.callAsConstructor(runtime, promiseExecutor);
return promise;
});
jsiRuntime.global().setProperty(jsiRuntime, "FastRSACallPromise", std::move(bridgeCallPromise));
jsiRuntime.global().setProperty(jsiRuntime, "FastRSACallSync", std::move(bridgeCallSync));
}
void cleanup() {
}
} // namespace fastRSA