@annadata/capacitor-mqtt-quic 0.1.7 → 0.1.8
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/AnnadataCapacitorMqttQuic.podspec +2 -2
- package/Package.swift +59 -0
- package/README.md +57 -17
- package/android/NGTCP2_BUILD_INSTRUCTIONS.md +1 -1
- package/android/app/src/main/assets/capacitor.config.json +1 -1
- package/android/build.gradle +4 -1
- package/android/install/wolfssl-android/arm64-v8a/lib/libwolfssl.a +0 -0
- package/android/install/wolfssl-android/armeabi-v7a/lib/libwolfssl.a +0 -0
- package/android/install/wolfssl-android/x86_64/lib/libwolfssl.a +0 -0
- package/android/src/main/cpp/CMakeLists.txt +19 -5
- package/android/src/main/cpp/ngtcp2_jni.cpp +28 -16
- package/android/src/main/kotlin/ai/annadata/mqttquic/MqttQuicPlugin.kt +3 -3
- package/android/src/main/kotlin/ai/annadata/mqttquic/client/MQTTClient.kt +3 -4
- package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTTProtocol.kt +3 -3
- package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTTTypes.kt +15 -15
- package/android/src/main/kotlin/ai/annadata/mqttquic/quic/NGTCP2Client.kt +1 -0
- package/docs/IMPLEMENTATION_SUMMARY.md +1 -1
- package/docs/NGTCP2_IMPLEMENTATION_STATUS.md +1 -1
- package/docs/PRODUCTION_PUBLISH_STEPS.md +9 -3
- package/ios/{MqttQuicPlugin.podspec → AnnadataCapacitorMqttQuic.podspec} +4 -4
- package/ios/App/App/capacitor.config.json +1 -1
- package/ios/NGTCP2_BUILD_INSTRUCTIONS.md +3 -3
- package/ios/Package.swift +7 -8
- package/ios/Tests/MQTTProtocolTests.swift +1 -1
- package/ios/libs/libnghttp3.a +0 -0
- package/ios/libs/libngtcp2.a +0 -0
- package/ios/libs/libngtcp2_crypto_wolfssl.a +0 -0
- package/ios/libs/libwolfssl.a +0 -0
- package/ios/libs-simulator/libnghttp3.a +0 -0
- package/ios/libs-simulator/libngtcp2.a +0 -0
- package/ios/libs-simulator/libngtcp2_crypto_wolfssl.a +0 -0
- package/ios/libs-simulator/libwolfssl.a +0 -0
- package/ios/libs-simulator-x86_64/libnghttp3.a +0 -0
- package/ios/libs-simulator-x86_64/libngtcp2.a +0 -0
- package/ios/libs-simulator-x86_64/libngtcp2_crypto_wolfssl.a +0 -0
- package/ios/libs-simulator-x86_64/libwolfssl.a +0 -0
- package/package.json +5 -2
|
@@ -8,8 +8,8 @@ Pod::Spec.new do |s|
|
|
|
8
8
|
s.summary = 'MQTT-over-QUIC Capacitor plugin (iOS)'
|
|
9
9
|
s.license = package['license']
|
|
10
10
|
s.homepage = 'https://github.com/annadata/capacitor-mqtt-quic'
|
|
11
|
-
s.author = 'Yakub Mohammad'
|
|
12
|
-
s.authors = { 'Yakub Mohammad' => 'yakub@annadata.ai' }
|
|
11
|
+
s.author = 'Mr. Yakub Mohammad'
|
|
12
|
+
s.authors = { 'Mr. Yakub Mohammad' => 'yakub@annadata.ai' }
|
|
13
13
|
s.source = { :git => 'https://github.com/annadata/capacitor-mqtt-quic', :tag => s.version.to_s }
|
|
14
14
|
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
15
15
|
s.resources = ['ios/Sources/MqttQuicPlugin/Resources/*.pem']
|
package/Package.swift
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
// AnnadataCapacitorMqttQuic – Swift Package for Capacitor 8 (SPM).
|
|
5
|
+
// At plugin root so Capacitor's SPM logic detects and adds it to CapApp-SPM automatically.
|
|
6
|
+
// Requires ios/libs/MqttQuicLibs.xcframework. After building (see build-native.sh), run:
|
|
7
|
+
// cd ios && ./create-xcframework.sh
|
|
8
|
+
let package = Package(
|
|
9
|
+
name: "AnnadataCapacitorMqttQuic",
|
|
10
|
+
platforms: [.iOS(.v15)],
|
|
11
|
+
products: [
|
|
12
|
+
.library(
|
|
13
|
+
name: "AnnadataCapacitorMqttQuic",
|
|
14
|
+
targets: ["AnnadataCapacitorMqttQuic"]
|
|
15
|
+
)
|
|
16
|
+
],
|
|
17
|
+
dependencies: [
|
|
18
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
|
|
19
|
+
],
|
|
20
|
+
targets: [
|
|
21
|
+
.binaryTarget(
|
|
22
|
+
name: "MqttQuicLibs",
|
|
23
|
+
path: "ios/libs/MqttQuicLibs.xcframework"
|
|
24
|
+
),
|
|
25
|
+
.target(
|
|
26
|
+
name: "NGTCP2Bridge",
|
|
27
|
+
dependencies: ["MqttQuicLibs"],
|
|
28
|
+
path: "ios/Sources/MqttQuicPlugin/QUIC",
|
|
29
|
+
sources: ["NGTCP2Bridge.mm"],
|
|
30
|
+
publicHeadersPath: ".",
|
|
31
|
+
cxxSettings: [
|
|
32
|
+
.define("NGTCP2_ENABLED"),
|
|
33
|
+
.define("NGHTTP3_ENABLED"),
|
|
34
|
+
.headerSearchPath("../../../include")
|
|
35
|
+
],
|
|
36
|
+
linkerSettings: [
|
|
37
|
+
.linkedLibrary("c++")
|
|
38
|
+
]
|
|
39
|
+
),
|
|
40
|
+
.target(
|
|
41
|
+
name: "AnnadataCapacitorMqttQuic",
|
|
42
|
+
dependencies: [
|
|
43
|
+
"NGTCP2Bridge",
|
|
44
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm")
|
|
45
|
+
],
|
|
46
|
+
path: "ios/Sources/MqttQuicPlugin",
|
|
47
|
+
exclude: [
|
|
48
|
+
"MQTT/MQTT5ReasonCodes.swift.rej",
|
|
49
|
+
"QUIC/NGTCP2Bridge.mm",
|
|
50
|
+
"QUIC/NGTCP2Bridge.h"
|
|
51
|
+
],
|
|
52
|
+
resources: [.process("Resources")],
|
|
53
|
+
swiftSettings: [
|
|
54
|
+
.define("NGTCP2_ENABLED"),
|
|
55
|
+
.define("NGHTTP3_ENABLED")
|
|
56
|
+
]
|
|
57
|
+
)
|
|
58
|
+
]
|
|
59
|
+
)
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MQTT-over-QUIC Capacitor plugin for **iOS**, **Android**, and **Web (browser/PWA)**. Native: ngtcp2 + WolfSSL for QUIC; Web: MQTT over WebSocket (WSS), same API and event listeners.
|
|
4
4
|
|
|
5
|
-
**Capacitor:**
|
|
5
|
+
**Capacitor:** **8.0+** (tested with Capacitor 8).
|
|
6
6
|
|
|
7
7
|
**Features:**
|
|
8
8
|
- ✅ **MQTT 5.0** support with full properties and reason codes
|
|
@@ -20,7 +20,7 @@ MQTT-over-QUIC Capacitor plugin for **iOS**, **Android**, and **Web (browser/PWA
|
|
|
20
20
|
- Transport abstraction (StreamReader/StreamWriter)
|
|
21
21
|
- **Phase 2**: QUIC transport (ngtcp2) + stream adapters - **In Progress** ⏳
|
|
22
22
|
- Currently uses stub implementations for testing
|
|
23
|
-
- See [NGTCP2_INTEGRATION_PLAN.md](./NGTCP2_INTEGRATION_PLAN.md) for build instructions
|
|
23
|
+
- See [NGTCP2_INTEGRATION_PLAN.md](./docs/NGTCP2_INTEGRATION_PLAN.md) for build instructions
|
|
24
24
|
- **Phase 3**: MQTT client API + Capacitor plugin bridge - **Complete** ✅
|
|
25
25
|
- **Phase 4**: Platform integration in annadata-production - **Complete** ✅
|
|
26
26
|
|
|
@@ -274,7 +274,7 @@ await MqttQuic.publish({
|
|
|
274
274
|
| **Reason Codes** | Detailed error information | Better debugging |
|
|
275
275
|
| **Topic Aliases** | Reduce bandwidth | High-frequency publishing |
|
|
276
276
|
|
|
277
|
-
See [MQTT5_IMPLEMENTATION_COMPLETE.md](./MQTT5_IMPLEMENTATION_COMPLETE.md) for full details.
|
|
277
|
+
See [MQTT5_IMPLEMENTATION_COMPLETE.md](./docs/MQTT5_IMPLEMENTATION_COMPLETE.md) for full details.
|
|
278
278
|
|
|
279
279
|
## TypeScript Interface
|
|
280
280
|
|
|
@@ -357,22 +357,25 @@ This script builds WolfSSL → nghttp3 → ngtcp2 in the correct order for both
|
|
|
357
357
|
For detailed manual build instructions, see:
|
|
358
358
|
- **iOS**: [ios/NGTCP2_BUILD_INSTRUCTIONS.md](./ios/NGTCP2_BUILD_INSTRUCTIONS.md)
|
|
359
359
|
- **Android**: [android/NGTCP2_BUILD_INSTRUCTIONS.md](./android/NGTCP2_BUILD_INSTRUCTIONS.md)
|
|
360
|
-
- **Full Plan**: [NGTCP2_INTEGRATION_PLAN.md](./NGTCP2_INTEGRATION_PLAN.md)
|
|
360
|
+
- **Full Plan**: [NGTCP2_INTEGRATION_PLAN.md](./docs/NGTCP2_INTEGRATION_PLAN.md)
|
|
361
361
|
|
|
362
362
|
**Prerequisites:**
|
|
363
|
-
- iOS: macOS with Xcode
|
|
363
|
+
- iOS: macOS with Xcode 15+
|
|
364
364
|
- Android: Android Studio with NDK r25+ (auto-detected from `$ANDROID_HOME`)
|
|
365
365
|
|
|
366
366
|
## Production / First-time build
|
|
367
367
|
|
|
368
|
-
When you install the plugin from npm (`npm install @annadata/capacitor-mqtt-quic`), the published package may include **prebuilt native libs** (iOS and optionally Android, both using **WolfSSL**).
|
|
368
|
+
When you install the plugin from npm (`npm install @annadata/capacitor-mqtt-quic`), the published package **may** include **prebuilt native libs** (iOS and optionally Android, both using **WolfSSL**). If it does (a "complete" / zero-config package), you only need:
|
|
369
369
|
|
|
370
370
|
```bash
|
|
371
371
|
npm install @annadata/capacitor-mqtt-quic
|
|
372
372
|
npx cap sync
|
|
373
|
+
ionic cap run android # or ios
|
|
373
374
|
```
|
|
374
375
|
|
|
375
|
-
**If your Android build fails with "WolfSSL not found"**,
|
|
376
|
+
**If your Android build fails with "WolfSSL not found"**, the package you installed does not include prebuilt Android libs. Do **one** of the following.
|
|
377
|
+
|
|
378
|
+
**Option A – One-time build (from your app project root, requires Android NDK r25+):** Both iOS and Android use **WolfSSL** as the TLS backend (license/size/QUIC support):
|
|
376
379
|
|
|
377
380
|
```bash
|
|
378
381
|
cd node_modules/@annadata/capacitor-mqtt-quic
|
|
@@ -402,14 +405,51 @@ Or add to your app’s `package.json` and run once:
|
|
|
402
405
|
"setup:wolfssl-android": "cd node_modules/@annadata/capacitor-mqtt-quic && ./build-native.sh --android-only --abi arm64-v8a && ./build-native.sh --android-only --abi armeabi-v7a && ./build-native.sh --android-only --abi x86_64"
|
|
403
406
|
```
|
|
404
407
|
|
|
405
|
-
**
|
|
408
|
+
**Option B – Use a complete package:** Reinstall a version of the plugin that was published with Android prebuilts (see *Publishing a complete package* below). Then no one-time build is needed.
|
|
409
|
+
|
|
410
|
+
**iOS:** The plugin typically ships with vendored static libs (`ios/libs/`) using WolfSSL. If you built the plugin from source and those are missing, run from the plugin repo: `./build-native.sh --ios-only`, then pack/publish.
|
|
411
|
+
|
|
412
|
+
### Publishing a complete (zero-config) package
|
|
413
|
+
|
|
414
|
+
So that **clients have no native build step**, build Android (and iOS) prebuilts **before** publishing, then publish. The tarball will include `android/install/` and consumers can `npm install` and run the app without running `build-native.sh`.
|
|
415
|
+
|
|
416
|
+
From the **plugin repo** (capacitor-mqtt-quic), before `npm publish`:
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
# 1) Android prebuilts for all ABIs (required for zero-config Android)
|
|
420
|
+
npm run build:android-prebuilts
|
|
421
|
+
|
|
422
|
+
# 2) iOS prebuilts (if not already present)
|
|
423
|
+
./build-native.sh --ios-only
|
|
424
|
+
|
|
425
|
+
# 3) Build JS and publish (clean does not remove android/install or ios/libs)
|
|
426
|
+
npm run build
|
|
427
|
+
npm run clean:build-artifacts
|
|
428
|
+
npm version patch # or minor
|
|
429
|
+
npm publish --access public
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
See **docs/PRODUCTION_PUBLISH_STEPS.md** for the full checklist.
|
|
433
|
+
|
|
434
|
+
### Connection error: `{"code":"UNIMPLEMENTED"}`
|
|
435
|
+
|
|
436
|
+
Capacitor returns this when the **native plugin method is not found** on the current platform. Common causes and fixes:
|
|
437
|
+
|
|
438
|
+
| Platform | Check |
|
|
439
|
+
|----------|--------|
|
|
440
|
+
| **iOS** | Plugin must be linked. Run `npx cap sync ios` and `cd ios && pod install`, then rebuild in Xcode. Ensure `@annadata/capacitor-mqtt-quic` is in your app’s `package.json` and that the iOS project includes the plugin (Capacitor should auto-discover it). If you use a custom Podfile, ensure the AnnadataCapacitorMqttQuic plugin target is included. |
|
|
441
|
+
| **Android** | Run `npx cap sync android` and rebuild. If you see "WolfSSL not found", run the one-time native build (see above). |
|
|
442
|
+
| **Web / browser** | In browser, the plugin uses the **web** implementation (WSS or WebTransport). If you get UNIMPLEMENTED in the browser, the app may be resolving the native bridge instead of the web plugin—e.g. wrong `capacitor.config` or build. Ensure you’re opening the app as a web build (e.g. `ionic serve` or `cap run web`), not a native app with a WebView. |
|
|
443
|
+
|
|
444
|
+
After adding the plugin or changing native code, always run **`npx cap sync`** and on iOS **`pod install`**, then rebuild the native app.
|
|
406
445
|
|
|
407
446
|
## Development
|
|
408
447
|
|
|
409
448
|
### Build Plugin
|
|
410
449
|
|
|
411
450
|
```bash
|
|
412
|
-
|
|
451
|
+
git clone https://github.com/annadata/capacitor-mqtt-quic.git
|
|
452
|
+
cd capacitor-mqtt-quic
|
|
413
453
|
npm install
|
|
414
454
|
npm run build
|
|
415
455
|
```
|
|
@@ -417,8 +457,8 @@ npm run build
|
|
|
417
457
|
### Add to Capacitor App
|
|
418
458
|
|
|
419
459
|
```bash
|
|
420
|
-
cd
|
|
421
|
-
npm
|
|
460
|
+
cd your-capacitor-app
|
|
461
|
+
npm install @annadata/capacitor-mqtt-quic
|
|
422
462
|
npx cap sync
|
|
423
463
|
```
|
|
424
464
|
|
|
@@ -443,14 +483,14 @@ await MqttQuic.connect({
|
|
|
443
483
|
|
|
444
484
|
## Publishing (maintainers)
|
|
445
485
|
|
|
446
|
-
To pack the plugin **with native libs** and publish to npm, follow **[PRODUCTION_PUBLISH_STEPS.md](./PRODUCTION_PUBLISH_STEPS.md)**.
|
|
486
|
+
To pack the plugin **with native libs** and publish to npm, follow **[PRODUCTION_PUBLISH_STEPS.md](./docs/PRODUCTION_PUBLISH_STEPS.md)**.
|
|
447
487
|
|
|
448
488
|
## Documentation
|
|
449
489
|
|
|
450
|
-
- [Implementation Summary](./IMPLEMENTATION_SUMMARY.md) - Complete project overview
|
|
451
|
-
- [MQTT 5.0 Implementation](./MQTT5_IMPLEMENTATION_COMPLETE.md) - MQTT 5.0 features and usage
|
|
452
|
-
- [ngtcp2 Integration Plan](./NGTCP2_INTEGRATION_PLAN.md) - Build instructions for real QUIC
|
|
453
|
-
- [MQTT Version Analysis](./MQTT_VERSION_ANALYSIS.md) - Why MQTT 5.0?
|
|
490
|
+
- [Implementation Summary](./docs/IMPLEMENTATION_SUMMARY.md) - Complete project overview
|
|
491
|
+
- [MQTT 5.0 Implementation](./docs/MQTT5_IMPLEMENTATION_COMPLETE.md) - MQTT 5.0 features and usage
|
|
492
|
+
- [ngtcp2 Integration Plan](./docs/NGTCP2_INTEGRATION_PLAN.md) - Build instructions for real QUIC
|
|
493
|
+
- [MQTT Version Analysis](./docs/MQTT_VERSION_ANALYSIS.md) - Why MQTT 5.0?
|
|
454
494
|
|
|
455
495
|
## Web / browser support
|
|
456
496
|
|
|
@@ -522,7 +562,7 @@ await MqttQuic.connect({
|
|
|
522
562
|
- **iOS:** 15.0+
|
|
523
563
|
- **Android:** API 21+ (Android 5.0+)
|
|
524
564
|
- **Web:** Any modern browser; MQTT over WSS
|
|
525
|
-
- **Capacitor:**
|
|
565
|
+
- **Capacitor:** 8.0+
|
|
526
566
|
- **QUIC:** ngtcp2 + WolfSSL on native; on web, optional WebTransport (browser's HTTP/3/QUIC) when server supports it
|
|
527
567
|
|
|
528
568
|
## Author
|
|
@@ -337,4 +337,4 @@ After building ngtcp2/nghttp3:
|
|
|
337
337
|
2. Replace `QuicClientStub` with `NGTCP2Client` in `MQTTClient.kt`
|
|
338
338
|
3. Test connection to MQTT server over QUIC
|
|
339
339
|
|
|
340
|
-
See
|
|
340
|
+
See [NGTCP2_INTEGRATION_PLAN.md](../docs/NGTCP2_INTEGRATION_PLAN.md) for detailed implementation guide.
|
package/android/build.gradle
CHANGED
|
@@ -36,7 +36,10 @@ android {
|
|
|
36
36
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
37
37
|
externalNativeBuild {
|
|
38
38
|
cmake {
|
|
39
|
-
arguments "-DANDROID_STL=c++_shared"
|
|
39
|
+
arguments "-DANDROID_STL=c++_shared",
|
|
40
|
+
"-DWOLFSSL_ROOT_DIR=${file('install/wolfssl-android').absolutePath}",
|
|
41
|
+
"-DNGTCP2_INSTALL_DIR=${file('install/ngtcp2-android').absolutePath}",
|
|
42
|
+
"-DNGHTTP3_INSTALL_DIR=${file('install/nghttp3-android').absolutePath}"
|
|
40
43
|
cppFlags "-std=c++17"
|
|
41
44
|
}
|
|
42
45
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -14,9 +14,10 @@ endif()
|
|
|
14
14
|
# WolfSSL path (same layout as iOS: TLS backend for ngtcp2). Override via -DWOLFSSL_ROOT_DIR=...
|
|
15
15
|
if(NOT WOLFSSL_ROOT_DIR)
|
|
16
16
|
set(WOLFSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../install/wolfssl-android" CACHE PATH "Path to WolfSSL for Android")
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
endif()
|
|
18
|
+
# Prefer ABI-specific subdir when present (e.g. when WOLFSSL_ROOT_DIR is passed as base path from Gradle)
|
|
19
|
+
if(EXISTS "${WOLFSSL_ROOT_DIR}/${ANDROID_ABI}")
|
|
20
|
+
set(WOLFSSL_ROOT_DIR "${WOLFSSL_ROOT_DIR}/${ANDROID_ABI}" CACHE PATH "Path to WolfSSL for Android (ABI)" FORCE)
|
|
20
21
|
endif()
|
|
21
22
|
if(NOT WOLFSSL_INCLUDE_DIR AND EXISTS "${WOLFSSL_ROOT_DIR}/include")
|
|
22
23
|
set(WOLFSSL_INCLUDE_DIR "${WOLFSSL_ROOT_DIR}/include")
|
|
@@ -25,7 +26,12 @@ if(NOT WOLFSSL_LIBRARY AND EXISTS "${WOLFSSL_ROOT_DIR}/lib/libwolfssl.a")
|
|
|
25
26
|
set(WOLFSSL_LIBRARY "${WOLFSSL_ROOT_DIR}/lib/libwolfssl.a")
|
|
26
27
|
endif()
|
|
27
28
|
if(NOT WOLFSSL_LIBRARY OR NOT WOLFSSL_INCLUDE_DIR)
|
|
28
|
-
message(FATAL_ERROR
|
|
29
|
+
message(FATAL_ERROR
|
|
30
|
+
"WolfSSL not found at ${WOLFSSL_ROOT_DIR}. "
|
|
31
|
+
"One-time fix (from your app project root): "
|
|
32
|
+
"cd node_modules/@annadata/capacitor-mqtt-quic && "
|
|
33
|
+
"./build-native.sh --android-only --abi ${ANDROID_ABI} "
|
|
34
|
+
"(repeat for armeabi-v7a, x86_64). See plugin README 'Production / First-time build'.")
|
|
29
35
|
endif()
|
|
30
36
|
|
|
31
37
|
# ngtcp2 install/source directories (adjust as needed)
|
|
@@ -46,6 +52,14 @@ if(NOT NGHTTP3_INSTALL_DIR)
|
|
|
46
52
|
endif()
|
|
47
53
|
set(NGHTTP3_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../nghttp3" CACHE PATH "Path to nghttp3 source")
|
|
48
54
|
|
|
55
|
+
# Prefer ABI-specific subdir when install dirs are passed as base path from Gradle
|
|
56
|
+
if(EXISTS "${NGTCP2_INSTALL_DIR}/${ANDROID_ABI}")
|
|
57
|
+
set(NGTCP2_INSTALL_DIR "${NGTCP2_INSTALL_DIR}/${ANDROID_ABI}" CACHE PATH "Path to ngtcp2 install (ABI)" FORCE)
|
|
58
|
+
endif()
|
|
59
|
+
if(EXISTS "${NGHTTP3_INSTALL_DIR}/${ANDROID_ABI}")
|
|
60
|
+
set(NGHTTP3_INSTALL_DIR "${NGHTTP3_INSTALL_DIR}/${ANDROID_ABI}" CACHE PATH "Path to nghttp3 install (ABI)" FORCE)
|
|
61
|
+
endif()
|
|
62
|
+
|
|
49
63
|
# Prefer installed libraries (WolfSSL backend: libngtcp2_crypto_wolfssl.a), fallback to source build
|
|
50
64
|
set(NGTCP2_INCLUDE_DIR "")
|
|
51
65
|
set(NGTCP2_LIBRARY "")
|
|
@@ -112,7 +126,7 @@ target_include_directories(ngtcp2_client PRIVATE
|
|
|
112
126
|
)
|
|
113
127
|
|
|
114
128
|
# Link libraries: WolfSSL + ngtcp2 (same TLS backend as iOS)
|
|
115
|
-
target_link_libraries(ngtcp2_client
|
|
129
|
+
target_link_libraries(ngtcp2_client PRIVATE
|
|
116
130
|
${WOLFSSL_LIBRARY}
|
|
117
131
|
log
|
|
118
132
|
)
|
|
@@ -188,7 +188,7 @@ class QuicClient {
|
|
|
188
188
|
if (!conn_) {
|
|
189
189
|
return 0;
|
|
190
190
|
}
|
|
191
|
-
int rv = ngtcp2_conn_shutdown_stream_write(conn_, stream_id, 0);
|
|
191
|
+
int rv = ngtcp2_conn_shutdown_stream_write(conn_, 0, stream_id, 0);
|
|
192
192
|
if (rv != 0) {
|
|
193
193
|
setError(ngtcp2_strerror(rv));
|
|
194
194
|
return -1;
|
|
@@ -266,12 +266,12 @@ class QuicClient {
|
|
|
266
266
|
if (fd == -1) {
|
|
267
267
|
continue;
|
|
268
268
|
}
|
|
269
|
-
if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
|
|
269
|
+
if (::connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
|
|
270
270
|
memcpy(&remote_addr_, rp->ai_addr, rp->ai_addrlen);
|
|
271
271
|
remote_addrlen_ = (socklen_t)rp->ai_addrlen;
|
|
272
272
|
break;
|
|
273
273
|
}
|
|
274
|
-
close(fd);
|
|
274
|
+
::close(fd);
|
|
275
275
|
fd = -1;
|
|
276
276
|
}
|
|
277
277
|
freeaddrinfo(res);
|
|
@@ -284,7 +284,7 @@ class QuicClient {
|
|
|
284
284
|
if (getsockname(fd, (struct sockaddr *)&local_addr_, &local_addrlen_) !=
|
|
285
285
|
0) {
|
|
286
286
|
setError("getsockname failed");
|
|
287
|
-
close(fd);
|
|
287
|
+
::close(fd);
|
|
288
288
|
return -1;
|
|
289
289
|
}
|
|
290
290
|
|
|
@@ -333,17 +333,21 @@ class QuicClient {
|
|
|
333
333
|
bool ca_loaded = false;
|
|
334
334
|
const char *ca_file = std::getenv("MQTT_QUIC_CA_FILE");
|
|
335
335
|
const char *ca_path = std::getenv("MQTT_QUIC_CA_PATH");
|
|
336
|
-
|
|
337
|
-
|
|
336
|
+
const char *file_arg = (ca_file && ca_file[0] != '\0') ? ca_file : nullptr;
|
|
337
|
+
const char *path_arg = (ca_path && ca_path[0] != '\0') ? ca_path : nullptr;
|
|
338
|
+
if (file_arg || path_arg) {
|
|
339
|
+
if (wolfSSL_CTX_load_verify_locations(ssl_ctx_, file_arg, path_arg) == 1) {
|
|
340
|
+
ca_loaded = true;
|
|
341
|
+
} else {
|
|
338
342
|
setError("Failed to load CA bundle from MQTT_QUIC_CA_FILE/CA_PATH");
|
|
339
343
|
return -1;
|
|
340
344
|
}
|
|
345
|
+
}
|
|
346
|
+
if (!ca_loaded && wolfSSL_CTX_set_default_verify_paths(ssl_ctx_) == 1) {
|
|
341
347
|
ca_loaded = true;
|
|
342
348
|
}
|
|
343
|
-
if (!ca_loaded) {
|
|
344
|
-
|
|
345
|
-
ca_loaded = true;
|
|
346
|
-
}
|
|
349
|
+
if (!ca_loaded && wolfSSL_CTX_load_system_CA_certs(ssl_ctx_) == 1) {
|
|
350
|
+
ca_loaded = true;
|
|
347
351
|
}
|
|
348
352
|
if (!ca_loaded) {
|
|
349
353
|
setError("No CA bundle available for TLS verification");
|
|
@@ -660,15 +664,15 @@ class QuicClient {
|
|
|
660
664
|
ssl_ctx_ = nullptr;
|
|
661
665
|
}
|
|
662
666
|
if (fd_ != -1) {
|
|
663
|
-
close(fd_);
|
|
667
|
+
::close(fd_);
|
|
664
668
|
fd_ = -1;
|
|
665
669
|
}
|
|
666
670
|
if (wakeup_fds_[0] != -1) {
|
|
667
|
-
close(wakeup_fds_[0]);
|
|
671
|
+
::close(wakeup_fds_[0]);
|
|
668
672
|
wakeup_fds_[0] = -1;
|
|
669
673
|
}
|
|
670
674
|
if (wakeup_fds_[1] != -1) {
|
|
671
|
-
close(wakeup_fds_[1]);
|
|
675
|
+
::close(wakeup_fds_[1]);
|
|
672
676
|
wakeup_fds_[1] = -1;
|
|
673
677
|
}
|
|
674
678
|
}
|
|
@@ -740,10 +744,11 @@ class QuicClient {
|
|
|
740
744
|
return 0;
|
|
741
745
|
}
|
|
742
746
|
|
|
743
|
-
static int stream_close_cb(ngtcp2_conn *conn,
|
|
744
|
-
|
|
745
|
-
void *stream_user_data) {
|
|
747
|
+
static int stream_close_cb(ngtcp2_conn *conn, uint32_t flags,
|
|
748
|
+
int64_t stream_id, uint64_t app_error_code,
|
|
749
|
+
void *user_data, void *stream_user_data) {
|
|
746
750
|
(void)conn;
|
|
751
|
+
(void)flags;
|
|
747
752
|
(void)app_error_code;
|
|
748
753
|
(void)stream_user_data;
|
|
749
754
|
auto *client = static_cast<QuicClient *>(user_data);
|
|
@@ -926,4 +931,11 @@ Java_ai_annadata_mqttquic_quic_NGTCP2Client_nativeGetLastError(
|
|
|
926
931
|
return env->NewStringUTF(it->second->last_error());
|
|
927
932
|
}
|
|
928
933
|
|
|
934
|
+
// Debug-build alias: Kotlin/AGP can mangle the method name to include the module suffix.
|
|
935
|
+
JNIEXPORT jstring JNICALL
|
|
936
|
+
Java_ai_annadata_mqttquic_quic_NGTCP2Client_nativeGetLastError_00024annadata_1capacitor_1mqtt_1quic_1debug__J(
|
|
937
|
+
JNIEnv *env, jobject thiz, jlong connHandle) {
|
|
938
|
+
return Java_ai_annadata_mqttquic_quic_NGTCP2Client_nativeGetLastError(env, thiz, connHandle);
|
|
939
|
+
}
|
|
940
|
+
|
|
929
941
|
} // extern "C"
|
|
@@ -100,7 +100,7 @@ class MqttQuicPlugin : Plugin() {
|
|
|
100
100
|
notifyListeners("message", data)
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
client.connect(host, port, clientId, username, password, cleanSession, keepalive, sessionExpiryInterval)
|
|
103
|
+
client.connect(host, port, clientId, username, password, cleanSession ?: true, keepalive ?: 20, sessionExpiryInterval)
|
|
104
104
|
call.resolve(JSObject().put("connected", true))
|
|
105
105
|
notifyListeners("connected", JSObject().put("connected", true))
|
|
106
106
|
} catch (e: Exception) {
|
|
@@ -199,7 +199,7 @@ class MqttQuicPlugin : Plugin() {
|
|
|
199
199
|
val properties = mutableMapOf<Int, Any>()
|
|
200
200
|
messageExpiryInterval?.let { properties[MQTT5PropertyType.MESSAGE_EXPIRY_INTERVAL.toInt()] = it }
|
|
201
201
|
contentType?.let { properties[MQTT5PropertyType.CONTENT_TYPE.toInt()] = it }
|
|
202
|
-
client.publish(topic, data, minOf(qos, 2), if (properties.isNotEmpty()) properties else null)
|
|
202
|
+
client.publish(topic, data, minOf(qos ?: 0, 2), if (properties.isNotEmpty()) properties else null)
|
|
203
203
|
call.resolve(JSObject().put("success", true))
|
|
204
204
|
} catch (e: Exception) {
|
|
205
205
|
val msg = e.message ?: "Publish failed"
|
|
@@ -226,7 +226,7 @@ class MqttQuicPlugin : Plugin() {
|
|
|
226
226
|
|
|
227
227
|
scope.launch {
|
|
228
228
|
try {
|
|
229
|
-
client.subscribe(topic, minOf(qos, 2), subscriptionIdentifier)
|
|
229
|
+
client.subscribe(topic, minOf(qos ?: 0, 2), subscriptionIdentifier)
|
|
230
230
|
call.resolve(JSObject().put("success", true))
|
|
231
231
|
} catch (e: Exception) {
|
|
232
232
|
call.reject(e.message ?: "Subscribe failed")
|
|
@@ -372,9 +372,9 @@ class MQTTClient {
|
|
|
372
372
|
/** Send PINGREQ at effectiveKeepalive interval so server sees activity and does not close (idle/keepalive). [MQTT-3.1.2-20] */
|
|
373
373
|
private fun startKeepaliveLoop() {
|
|
374
374
|
keepaliveJob?.cancel()
|
|
375
|
-
val ka = lock.withLock { effectiveKeepalive }
|
|
376
|
-
if (ka <= 0) return
|
|
377
375
|
keepaliveJob = scope.launch {
|
|
376
|
+
val ka = lock.withLock { effectiveKeepalive }
|
|
377
|
+
if (ka <= 0) return@launch
|
|
378
378
|
while (isActive) {
|
|
379
379
|
delay(ka * 1000L) // seconds to ms
|
|
380
380
|
val (w, stillConnected) = lock.withLock {
|
|
@@ -428,8 +428,7 @@ class MQTTClient {
|
|
|
428
428
|
if (activeProtocolVersion == MQTTProtocolLevel.V5) {
|
|
429
429
|
MQTT5Protocol.parsePublishV5(rest, 0, qos, topicAliasMap)
|
|
430
430
|
} else {
|
|
431
|
-
|
|
432
|
-
Triple(t.first, t.second, t.third)
|
|
431
|
+
MQTTProtocol.parsePublish(rest, 0, qos)
|
|
433
432
|
}
|
|
434
433
|
}
|
|
435
434
|
|
|
@@ -201,9 +201,9 @@ object MQTTProtocol {
|
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
203
|
* Parse PUBLISH payload (after fixed header).
|
|
204
|
-
* Returns (topic, packetId?, payload
|
|
204
|
+
* Returns (topic, packetId?, payload). packetId only for QoS > 0.
|
|
205
205
|
*/
|
|
206
|
-
fun parsePublish(data: ByteArray, offset: Int, qos: Int): Triple<String, Int?, ByteArray
|
|
206
|
+
fun parsePublish(data: ByteArray, offset: Int, qos: Int): Triple<String, Int?, ByteArray> {
|
|
207
207
|
var off = offset
|
|
208
208
|
val (topic, next) = decodeString(data, off)
|
|
209
209
|
off = next
|
|
@@ -214,7 +214,7 @@ object MQTTProtocol {
|
|
|
214
214
|
off += 2
|
|
215
215
|
}
|
|
216
216
|
val payload = data.copyOfRange(off, data.size)
|
|
217
|
-
return Triple(topic, pid, payload
|
|
217
|
+
return Triple(topic, pid, payload)
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
fun buildSubscribe(packetId: Int, topic: String, qos: Int = 0): ByteArray {
|
|
@@ -5,21 +5,21 @@ package ai.annadata.mqttquic.mqtt
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
object MQTTMessageType {
|
|
8
|
-
const val CONNECT: Byte = 0x10
|
|
9
|
-
const val CONNACK: Byte = 0x20
|
|
10
|
-
const val PUBLISH: Byte = 0x30
|
|
11
|
-
const val PUBACK: Byte = 0x40
|
|
12
|
-
const val PUBREC: Byte = 0x50
|
|
13
|
-
const val PUBREL: Byte = 0x62
|
|
14
|
-
const val PUBCOMP: Byte = 0x70
|
|
15
|
-
const val SUBSCRIBE: Byte = 0x82
|
|
16
|
-
const val SUBACK: Byte = 0x90
|
|
17
|
-
const val UNSUBSCRIBE: Byte = 0xA2
|
|
18
|
-
const val UNSUBACK: Byte = 0xB0
|
|
19
|
-
const val PINGREQ: Byte = 0xC0
|
|
20
|
-
const val PINGRESP: Byte = 0xD0
|
|
21
|
-
const val DISCONNECT: Byte = 0xE0
|
|
22
|
-
const val AUTH: Byte = 0xF0
|
|
8
|
+
const val CONNECT: Byte = 0x10.toByte()
|
|
9
|
+
const val CONNACK: Byte = 0x20.toByte()
|
|
10
|
+
const val PUBLISH: Byte = 0x30.toByte()
|
|
11
|
+
const val PUBACK: Byte = 0x40.toByte()
|
|
12
|
+
const val PUBREC: Byte = 0x50.toByte()
|
|
13
|
+
const val PUBREL: Byte = 0x62.toByte()
|
|
14
|
+
const val PUBCOMP: Byte = 0x70.toByte()
|
|
15
|
+
const val SUBSCRIBE: Byte = 0x82.toByte()
|
|
16
|
+
const val SUBACK: Byte = 0x90.toByte()
|
|
17
|
+
const val UNSUBSCRIBE: Byte = 0xA2.toByte()
|
|
18
|
+
const val UNSUBACK: Byte = 0xB0.toByte()
|
|
19
|
+
const val PINGREQ: Byte = 0xC0.toByte()
|
|
20
|
+
const val PINGRESP: Byte = 0xD0.toByte()
|
|
21
|
+
const val DISCONNECT: Byte = 0xE0.toByte()
|
|
22
|
+
const val AUTH: Byte = 0xF0.toByte()
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
object MQTTConnectFlags {
|
|
@@ -47,6 +47,7 @@ class NGTCP2Client : QuicClient {
|
|
|
47
47
|
private external fun nativeClose(connHandle: Long)
|
|
48
48
|
private external fun nativeIsConnected(connHandle: Long): Boolean
|
|
49
49
|
internal external fun nativeCloseStream(connHandle: Long, streamId: Long): Int
|
|
50
|
+
@JvmName("nativeGetLastError")
|
|
50
51
|
internal external fun nativeGetLastError(connHandle: Long): String
|
|
51
52
|
|
|
52
53
|
// Connection state
|
|
@@ -182,7 +182,7 @@ Implement `MqttQuicService` web fallback using `mqtt.js` or similar library.
|
|
|
182
182
|
```
|
|
183
183
|
capacitor-mqtt-quic/
|
|
184
184
|
├── ios/
|
|
185
|
-
│ ├──
|
|
185
|
+
│ ├── AnnadataCapacitorMqttQuic.podspec
|
|
186
186
|
│ └── Sources/MqttQuicPlugin/
|
|
187
187
|
│ ├── MQTT/ # Phase 1
|
|
188
188
|
│ ├── Transport/ # Phase 1, 2
|
|
@@ -129,7 +129,7 @@ The ngtcp2 integration replaces the stub QUIC implementations (`QuicClientStub`)
|
|
|
129
129
|
- Implement TLS 1.3 handshake
|
|
130
130
|
- Implement UDP packet handlers
|
|
131
131
|
|
|
132
|
-
4. **Update `
|
|
132
|
+
4. **Update `AnnadataCapacitorMqttQuic.podspec`:**
|
|
133
133
|
- Add ngtcp2 library linking
|
|
134
134
|
- Add header search paths
|
|
135
135
|
|
|
@@ -9,7 +9,7 @@ This checklist makes the plugin **production-grade**: pack everything needed (in
|
|
|
9
9
|
## Prerequisites
|
|
10
10
|
|
|
11
11
|
- Node.js 18+
|
|
12
|
-
- **iOS:** macOS, Xcode
|
|
12
|
+
- **iOS:** macOS, Xcode 15+
|
|
13
13
|
- **Android:** Android Studio, NDK r25+ (e.g. via `$ANDROID_HOME/ndk/<version>`)
|
|
14
14
|
- npm account with access to `@annadata` scope
|
|
15
15
|
|
|
@@ -32,9 +32,15 @@ This produces:
|
|
|
32
32
|
|
|
33
33
|
The podspec’s `vendored_libraries` point at `ios/libs/`; these **must** be present when you pack/publish.
|
|
34
34
|
|
|
35
|
-
### Android (
|
|
35
|
+
### Android (required for zero-config / “complete” package)
|
|
36
36
|
|
|
37
|
-
Android uses **WolfSSL** (same TLS backend as iOS).
|
|
37
|
+
Android uses **WolfSSL** (same TLS backend as iOS). To ship a **complete** plugin so clients don’t run any native build, build WolfSSL + nghttp3 + ngtcp2 for all ABIs:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm run build:android-prebuilts
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or manually:
|
|
38
44
|
|
|
39
45
|
```bash
|
|
40
46
|
./build-native.sh --android-only --abi arm64-v8a
|
|
@@ -3,7 +3,7 @@ require 'json'
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
4
|
|
|
5
5
|
Pod::Spec.new do |s|
|
|
6
|
-
s.name = '
|
|
6
|
+
s.name = 'AnnadataCapacitorMqttQuic'
|
|
7
7
|
s.version = package['version']
|
|
8
8
|
s.summary = 'MQTT-over-QUIC Capacitor plugin (iOS)'
|
|
9
9
|
s.license = package['license']
|
|
@@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
|
|
12
12
|
s.source = { :git => 'https://github.com/annadata/capacitor-mqtt-quic', :tag => s.version.to_s }
|
|
13
13
|
s.source_files = 'Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
14
|
s.resources = ['Sources/MqttQuicPlugin/Resources/*.pem']
|
|
15
|
-
s.ios.deployment_target = '
|
|
15
|
+
s.ios.deployment_target = '15.0'
|
|
16
16
|
s.dependency 'Capacitor'
|
|
17
17
|
s.swift_version = '5.1'
|
|
18
18
|
s.vendored_libraries = [
|
|
@@ -25,8 +25,8 @@ Pod::Spec.new do |s|
|
|
|
25
25
|
s.private_header_files = 'Sources/**/*.h', 'include/**/*.h'
|
|
26
26
|
s.header_mappings_dir = 'Sources'
|
|
27
27
|
s.pod_target_xcconfig = {
|
|
28
|
-
'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/
|
|
29
|
-
'LIBRARY_SEARCH_PATHS' => '$(PODS_ROOT)/
|
|
28
|
+
'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/AnnadataCapacitorMqttQuic/include/ngtcp2 $(PODS_ROOT)/AnnadataCapacitorMqttQuic/include/nghttp3 $(PODS_ROOT)/AnnadataCapacitorMqttQuic/include/wolfssl',
|
|
29
|
+
'LIBRARY_SEARCH_PATHS' => '$(PODS_ROOT)/AnnadataCapacitorMqttQuic/libs',
|
|
30
30
|
'OTHER_LDFLAGS' => '-lngtcp2 -lngtcp2_crypto_wolfssl -lnghttp3 -lwolfssl',
|
|
31
31
|
'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => 'NGTCP2_ENABLED NGHTTP3_ENABLED'
|
|
32
32
|
}
|
|
@@ -34,7 +34,7 @@ If you have access to pre-built ngtcp2, nghttp3, and OpenSSL libraries:
|
|
|
34
34
|
2. Place `libnghttp3.a` in `ios/libs/`
|
|
35
35
|
3. Place OpenSSL libraries (`libssl.a`, `libcrypto.a`) in `ios/libs/`
|
|
36
36
|
4. Place headers in `ios/include/ngtcp2/`, `ios/include/nghttp3/`, and `ios/include/openssl/`
|
|
37
|
-
5. Update `
|
|
37
|
+
5. Update `AnnadataCapacitorMqttQuic.podspec` to link against these libraries
|
|
38
38
|
|
|
39
39
|
### Option 2: Build from Source
|
|
40
40
|
|
|
@@ -154,7 +154,7 @@ Then clean and rebuild the iOS app so it links the new xcframework. See the app
|
|
|
154
154
|
|
|
155
155
|
### Option A: CocoaPods
|
|
156
156
|
|
|
157
|
-
Update `ios/
|
|
157
|
+
Update `ios/AnnadataCapacitorMqttQuic.podspec`:
|
|
158
158
|
|
|
159
159
|
```ruby
|
|
160
160
|
Pod::Spec.new do |s|
|
|
@@ -342,4 +342,4 @@ After building ngtcp2:
|
|
|
342
342
|
2. Replace `QuicClientStub` with `NGTCP2Client` in `MQTTClient.swift`
|
|
343
343
|
3. Test connection to MQTT server over QUIC
|
|
344
344
|
|
|
345
|
-
See
|
|
345
|
+
See [NGTCP2_INTEGRATION_PLAN.md](../docs/NGTCP2_INTEGRATION_PLAN.md) for detailed implementation guide.
|
package/ios/Package.swift
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
// swift-tools-version: 5.9
|
|
2
2
|
import PackageDescription
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
// Requires Libs/MqttQuicLibs.xcframework. After building
|
|
6
|
-
// (see build-openssl.sh, build-ngtcp2.sh, build-nghttp3.sh), run:
|
|
4
|
+
// AnnadataCapacitorMqttQuic – Swift Package for Capacitor 8 (SPM).
|
|
5
|
+
// Requires Libs/MqttQuicLibs.xcframework. After building (see build-native.sh), run:
|
|
7
6
|
// ./create-xcframework.sh
|
|
8
7
|
let package = Package(
|
|
9
|
-
name: "
|
|
10
|
-
platforms: [.iOS(.
|
|
8
|
+
name: "AnnadataCapacitorMqttQuic",
|
|
9
|
+
platforms: [.iOS(.v15)],
|
|
11
10
|
products: [
|
|
12
11
|
.library(
|
|
13
|
-
name: "
|
|
14
|
-
targets: ["
|
|
12
|
+
name: "AnnadataCapacitorMqttQuic",
|
|
13
|
+
targets: ["AnnadataCapacitorMqttQuic"]
|
|
15
14
|
)
|
|
16
15
|
],
|
|
17
16
|
dependencies: [
|
|
@@ -38,7 +37,7 @@ let package = Package(
|
|
|
38
37
|
]
|
|
39
38
|
),
|
|
40
39
|
.target(
|
|
41
|
-
name: "
|
|
40
|
+
name: "AnnadataCapacitorMqttQuic",
|
|
42
41
|
dependencies: [
|
|
43
42
|
"NGTCP2Bridge",
|
|
44
43
|
.product(name: "Capacitor", package: "capacitor-swift-pm")
|
package/ios/libs/libnghttp3.a
CHANGED
|
Binary file
|
package/ios/libs/libngtcp2.a
CHANGED
|
Binary file
|
|
Binary file
|
package/ios/libs/libwolfssl.a
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@annadata/capacitor-mqtt-quic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MQTT-over-QUIC client for Capacitor (iOS, Android, Web). Native: ngtcp2+WolfSSL; Web: MQTT over WebSocket (WSS), same API.",
|
|
6
6
|
"main": "dist/plugin.cjs.js",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"ios",
|
|
13
13
|
"android",
|
|
14
|
+
"Package.swift",
|
|
14
15
|
"AnnadataCapacitorMqttQuic.podspec",
|
|
15
16
|
"README.md",
|
|
16
17
|
"deps-versions.sh",
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
"build": "npm run build:tsc && npm run build:rollup",
|
|
22
23
|
"build:tsc": "npx tsc",
|
|
23
24
|
"build:rollup": "npx rollup -c rollup.config.js",
|
|
25
|
+
"build:android-prebuilts": "./build-native.sh --android-only --abi arm64-v8a && ./build-native.sh --android-only --abi armeabi-v7a && ./build-native.sh --android-only --abi x86_64",
|
|
24
26
|
"watch": "rollup -c rollup.config.js -w",
|
|
25
27
|
"lint": "eslint src --ext ts",
|
|
26
28
|
"prepack": "npm run clean:build-artifacts",
|
|
@@ -41,7 +43,8 @@
|
|
|
41
43
|
],
|
|
42
44
|
"capacitor": {
|
|
43
45
|
"ios": {
|
|
44
|
-
"src": "ios"
|
|
46
|
+
"src": "ios",
|
|
47
|
+
"name": "AnnadataCapacitorMqttQuic"
|
|
45
48
|
},
|
|
46
49
|
"android": {
|
|
47
50
|
"src": "android"
|