@orzattyholding/po 0.1.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.
- package/Cargo.toml +19 -0
- package/build.rs +5 -0
- package/demo_node.js +33 -0
- package/index.d.ts +22 -0
- package/index.js +315 -0
- package/package.json +20 -0
- package/po-napi.darwin-arm64.node +0 -0
- package/po-napi.linux-x64-gnu.node +0 -0
- package/po-napi.win32-x64-msvc.node +0 -0
- package/src/lib.rs +85 -0
package/Cargo.toml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "po-napi"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
authors = ["Dylan Orzatty <dylan@orzatty.com>"]
|
|
6
|
+
publish = false
|
|
7
|
+
|
|
8
|
+
[lib]
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
napi = { version = "2.16.4", features = ["async", "napi4", "tokio_rt"] }
|
|
13
|
+
napi-derive = "2.16.2"
|
|
14
|
+
tokio = { workspace = true }
|
|
15
|
+
po-node = { workspace = true }
|
|
16
|
+
po-session = { workspace = true }
|
|
17
|
+
|
|
18
|
+
[build-dependencies]
|
|
19
|
+
napi-build = "2.1.3"
|
package/build.rs
ADDED
package/demo_node.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const { PoClient } = require('./index.js');
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("🚀 Starting Protocol Orzatty Node.js Binding Test\n");
|
|
5
|
+
|
|
6
|
+
console.log(" [Server&Client] Initializing connection...");
|
|
7
|
+
const [server, client] = await Promise.all([
|
|
8
|
+
PoClient.bind(5544),
|
|
9
|
+
// Give bind a tiny fraction of a second to start listening before connect
|
|
10
|
+
new Promise(res => setTimeout(res, 200)).then(() => PoClient.connect("127.0.0.1:5544"))
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
console.log(` [Server] Node ID: ${server.nodeId}`);
|
|
14
|
+
console.log(` [Client] Node ID: ${client.nodeId}`);
|
|
15
|
+
|
|
16
|
+
// 3. Client sends a message
|
|
17
|
+
const msg = "Hello from Node.js land over E2EE UDP!";
|
|
18
|
+
console.log(`\n [Client] Sending: "${msg}"`);
|
|
19
|
+
await client.send(Buffer.from(msg));
|
|
20
|
+
|
|
21
|
+
// 4. Server receives it
|
|
22
|
+
const data = await server.recv();
|
|
23
|
+
console.log(` [Server] Received: "${data.toString('utf8')}"`);
|
|
24
|
+
|
|
25
|
+
// 5. Cleanup
|
|
26
|
+
console.log("\n Closing connections...");
|
|
27
|
+
await client.close();
|
|
28
|
+
await server.close();
|
|
29
|
+
|
|
30
|
+
console.log("✅ Node.js Bindings test passed!");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
main().catch(console.error);
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
export declare class PoClient {
|
|
7
|
+
/** Bind to a local port to accept incoming connections. */
|
|
8
|
+
static bind(port: number): Promise<PoClient>
|
|
9
|
+
/** Connect to a remote PO node. */
|
|
10
|
+
static connect(address: string): Promise<PoClient>
|
|
11
|
+
/** Get the cryptographic Node ID of this client. */
|
|
12
|
+
get nodeId(): string
|
|
13
|
+
/** Send a Buffer of data to the peer. */
|
|
14
|
+
send(data: Buffer): Promise<void>
|
|
15
|
+
/**
|
|
16
|
+
* Receive a Buffer of data from the peer.
|
|
17
|
+
* Returns undefined if the stream is closed gracefully.
|
|
18
|
+
*/
|
|
19
|
+
recv(): Promise<Buffer | null>
|
|
20
|
+
/** Gracefully close the connection. */
|
|
21
|
+
close(): Promise<void>
|
|
22
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'po-napi.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./po-napi.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('@orzatty/po-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'po-napi.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./po-napi.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('@orzatty/po-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'po-napi.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./po-napi.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('@orzatty/po-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'po-napi.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./po-napi.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('@orzatty/po-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'po-napi.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./po-napi.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('@orzatty/po-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'po-napi.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./po-napi.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('@orzatty/po-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'po-napi.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./po-napi.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('@orzatty/po-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'po-napi.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./po-napi.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('@orzatty/po-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'po-napi.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./po-napi.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('@orzatty/po-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'po-napi.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./po-napi.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('@orzatty/po-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'po-napi.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./po-napi.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('@orzatty/po-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'po-napi.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./po-napi.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('@orzatty/po-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'po-napi.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./po-napi.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('@orzatty/po-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'po-napi.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./po-napi.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('@orzatty/po-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'po-napi.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./po-napi.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('@orzatty/po-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'po-napi.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./po-napi.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('@orzatty/po-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'po-napi.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./po-napi.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@orzatty/po-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'po-napi.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./po-napi.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('@orzatty/po-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { PoClient } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.PoClient = PoClient
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orzattyholding/po",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Protocol Orzatty Node.js bindings (P2P E2EE QUIC)",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"napi": {
|
|
8
|
+
"name": "po-napi"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "napi build --platform --release",
|
|
12
|
+
"build:debug": "napi build --platform",
|
|
13
|
+
"test": "node demo_node.js"
|
|
14
|
+
},
|
|
15
|
+
"author": "Dylan Orzatty",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@napi-rs/cli": "^2.18.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/lib.rs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#![deny(clippy::all)]
|
|
2
|
+
|
|
3
|
+
use napi::bindgen_prelude::*;
|
|
4
|
+
use napi_derive::napi;
|
|
5
|
+
use po_node::Po;
|
|
6
|
+
use std::sync::Arc;
|
|
7
|
+
use tokio::sync::Mutex;
|
|
8
|
+
|
|
9
|
+
#[napi]
|
|
10
|
+
pub struct PoClient {
|
|
11
|
+
inner: Arc<Mutex<Po>>,
|
|
12
|
+
node_id: String,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#[napi]
|
|
16
|
+
impl PoClient {
|
|
17
|
+
/// Bind to a local port to accept incoming connections.
|
|
18
|
+
#[napi(factory)]
|
|
19
|
+
pub async fn bind(port: u32) -> Result<PoClient> {
|
|
20
|
+
let po = Po::bind(port as u16)
|
|
21
|
+
.await
|
|
22
|
+
.map_err(|e| Error::new(Status::GenericFailure, format!("Bind error: {e:?}")))?;
|
|
23
|
+
|
|
24
|
+
let node_id = po.node_id();
|
|
25
|
+
Ok(PoClient {
|
|
26
|
+
inner: Arc::new(Mutex::new(po)),
|
|
27
|
+
node_id,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Connect to a remote PO node.
|
|
32
|
+
#[napi(factory)]
|
|
33
|
+
pub async fn connect(address: String) -> Result<PoClient> {
|
|
34
|
+
let po = Po::connect(&address)
|
|
35
|
+
.await
|
|
36
|
+
.map_err(|e| Error::new(Status::GenericFailure, format!("Connect error: {e:?}")))?;
|
|
37
|
+
|
|
38
|
+
let node_id = po.node_id();
|
|
39
|
+
Ok(PoClient {
|
|
40
|
+
inner: Arc::new(Mutex::new(po)),
|
|
41
|
+
node_id,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Get the cryptographic Node ID of this client.
|
|
46
|
+
#[napi(getter)]
|
|
47
|
+
pub fn get_node_id(&self) -> String {
|
|
48
|
+
self.node_id.clone()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// Send a Buffer of data to the peer.
|
|
52
|
+
#[napi]
|
|
53
|
+
pub async fn send(&self, data: Buffer) -> Result<()> {
|
|
54
|
+
let mut po = self.inner.lock().await;
|
|
55
|
+
po.send(&data)
|
|
56
|
+
.await
|
|
57
|
+
.map_err(|e| Error::new(Status::GenericFailure, format!("Send error: {e:?}")))?;
|
|
58
|
+
Ok(())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// Receive a Buffer of data from the peer.
|
|
62
|
+
/// Returns undefined if the stream is closed gracefully.
|
|
63
|
+
#[napi]
|
|
64
|
+
pub async fn recv(&self) -> Result<Option<Buffer>> {
|
|
65
|
+
let mut po = self.inner.lock().await;
|
|
66
|
+
match po.recv().await {
|
|
67
|
+
Ok(Some((_channel, data))) => Ok(Some(data.into())),
|
|
68
|
+
Ok(None) => Ok(None),
|
|
69
|
+
Err(e) => Err(Error::new(
|
|
70
|
+
Status::GenericFailure,
|
|
71
|
+
format!("Recv error: {e:?}"),
|
|
72
|
+
)),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Gracefully close the connection.
|
|
77
|
+
#[napi]
|
|
78
|
+
pub async fn close(&self) -> Result<()> {
|
|
79
|
+
let mut po = self.inner.lock().await;
|
|
80
|
+
po.close()
|
|
81
|
+
.await
|
|
82
|
+
.map_err(|e| Error::new(Status::GenericFailure, format!("Close error: {e:?}")))?;
|
|
83
|
+
Ok(())
|
|
84
|
+
}
|
|
85
|
+
}
|