Merge Aidl into main mycelium lib

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2026-04-28 15:49:56 +02:00
parent 3b856d94f9
commit 4608ded1ae
21 changed files with 839 additions and 206 deletions
Generated
+628 -7
View File
@@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "addr2line"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aead"
version = "0.5.2"
@@ -70,6 +85,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.101"
@@ -249,6 +273,30 @@ dependencies = [
"tracing",
]
[[package]]
name = "backtrace"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-link 0.2.1",
]
[[package]]
name = "backtrace-ext"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
dependencies = [
"backtrace",
]
[[package]]
name = "base64"
version = "0.22.1"
@@ -354,6 +402,16 @@ dependencies = [
"syn 2.0.116",
]
[[package]]
name = "bstr"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.17.0"
@@ -468,6 +526,39 @@ dependencies = [
"rand_core 0.10.0",
]
[[package]]
name = "chrono"
version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
dependencies = [
"iana-time-zone",
"num-traits",
"windows-link 0.2.1",
]
[[package]]
name = "chrono-tz"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]]
name = "cipher"
version = "0.4.4"
@@ -507,6 +598,15 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
[[package]]
name = "convert_case"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -556,6 +656,16 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
@@ -681,6 +791,12 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "deunicode"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04"
[[package]]
name = "digest"
version = "0.10.7"
@@ -746,6 +862,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "downcast-rs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
[[package]]
name = "dyn-clone"
version = "1.0.20"
@@ -977,7 +1099,7 @@ dependencies = [
"log",
"rustversion",
"windows-link 0.2.1",
"windows-result",
"windows-result 0.3.4",
]
[[package]]
@@ -1041,6 +1163,36 @@ dependencies = [
"polyval",
]
[[package]]
name = "gimli"
version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
[[package]]
name = "globset"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
dependencies = [
"aho-corasick",
"bstr",
"log",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "globwalk"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
dependencies = [
"bitflags 2.9.0",
"ignore",
"walkdir",
]
[[package]]
name = "h2"
version = "0.4.8"
@@ -1260,6 +1412,15 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humansize"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
dependencies = [
"libm",
]
[[package]]
name = "hyper"
version = "1.6.0"
@@ -1324,6 +1485,30 @@ dependencies = [
"windows-registry",
]
[[package]]
name = "iana-time-zone"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core 0.62.2",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "icu_collections"
version = "1.5.0"
@@ -1469,6 +1654,22 @@ dependencies = [
"icu_properties",
]
[[package]]
name = "ignore"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
dependencies = [
"crossbeam-deque",
"globset",
"log",
"memchr",
"regex-automata",
"same-file",
"walkdir",
"winapi-util",
]
[[package]]
name = "indexmap"
version = "2.8.0"
@@ -1552,6 +1753,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "is_ci"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]]
name = "itoa"
version = "1.0.15"
@@ -1769,6 +1976,12 @@ version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "litemap"
version = "0.7.5"
@@ -1855,6 +2068,36 @@ dependencies = [
"autocfg",
]
[[package]]
name = "miette"
version = "7.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"
dependencies = [
"backtrace",
"backtrace-ext",
"cfg-if",
"miette-derive",
"owo-colors",
"supports-color",
"supports-hyperlinks",
"supports-unicode",
"terminal_size",
"textwrap",
"unicode-width 0.1.14",
]
[[package]]
name = "miette-derive"
version = "7.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.116",
]
[[package]]
name = "mime"
version = "0.3.17"
@@ -1867,6 +2110,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "1.2.0"
@@ -1928,7 +2180,10 @@ dependencies = [
"rcgen",
"redis",
"reed-solomon-erasure",
"regex",
"reqwest",
"rsbinder",
"rsbinder-aidl",
"rtnetlink",
"rustls",
"serde",
@@ -2218,6 +2473,15 @@ dependencies = [
"objc2-security",
]
[[package]]
name = "object"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"memchr",
]
[[package]]
name = "oid-registry"
version = "0.8.1"
@@ -2291,6 +2555,12 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "owo-colors"
version = "4.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d"
[[package]]
name = "parking"
version = "2.2.1"
@@ -2345,6 +2615,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "parse-zoneinfo"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
dependencies = [
"regex",
]
[[package]]
name = "pastey"
version = "0.1.1"
@@ -2367,6 +2646,87 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pest"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662"
dependencies = [
"memchr",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.116",
]
[[package]]
name = "pest_meta"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220"
dependencies = [
"pest",
"sha2",
]
[[package]]
name = "phf"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"rand 0.8.5",
]
[[package]]
name = "phf_shared"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.1.10"
@@ -2456,6 +2816,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "pretty-hex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a65843dfefbafd3c879c683306959a6de478443ffe9c9adf02f5976432402d7"
[[package]]
name = "prettyplease"
version = "0.2.37"
@@ -2477,7 +2843,7 @@ dependencies = [
"is-terminal",
"lazy_static",
"term",
"unicode-width",
"unicode-width 0.1.14",
]
[[package]]
@@ -2507,7 +2873,7 @@ dependencies = [
"bitflags 2.9.0",
"hex",
"procfs-core",
"rustix",
"rustix 0.38.44",
]
[[package]]
@@ -2818,6 +3184,18 @@ dependencies = [
"syn 2.0.116",
]
[[package]]
name = "regex"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
@@ -2940,6 +3318,51 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746"
[[package]]
name = "rsbinder"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8083f00eae89dabdac285d622f9844f0da16eca07e15b779e6b66aaedec3e9"
dependencies = [
"async-trait",
"downcast-rs",
"log",
"pretty-hex",
"rsbinder-aidl",
"rsproperties",
"rustix 1.1.4",
"tokio",
]
[[package]]
name = "rsbinder-aidl"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625505d53b7e80fedf1e07a4a4483aff82b430c07e6813dad7e9c1c70d0c0315"
dependencies = [
"convert_case",
"miette",
"pest",
"pest_derive",
"serde",
"tera",
"thiserror 2.0.12",
]
[[package]]
name = "rsproperties"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98d55abde44982a00d67a84809166ea8f5c143abc86818f555485f19766cfe4"
dependencies = [
"log",
"pretty-hex",
"rustix 1.1.4",
"thiserror 2.0.12",
"zerocopy 0.8.23",
"zerocopy-derive 0.8.23",
]
[[package]]
name = "rtnetlink"
version = "0.21.0"
@@ -2974,6 +3397,12 @@ dependencies = [
"serde_json",
]
[[package]]
name = "rustc-demangle"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
[[package]]
name = "rustc-hash"
version = "2.1.1"
@@ -3007,10 +3436,23 @@ dependencies = [
"bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys",
"linux-raw-sys 0.4.15",
"windows-sys 0.59.0",
]
[[package]]
name = "rustix"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
"bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys 0.12.1",
"windows-sys 0.61.2",
]
[[package]]
name = "rustls"
version = "0.23.38"
@@ -3185,6 +3627,17 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
@@ -3200,6 +3653,16 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
"errno",
"libc",
]
[[package]]
name = "simd_cesu8"
version = "1.1.1"
@@ -3216,6 +3679,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
[[package]]
name = "slab"
version = "0.4.9"
@@ -3225,6 +3694,16 @@ dependencies = [
"autocfg",
]
[[package]]
name = "slug"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724"
dependencies = [
"deunicode",
"wasm-bindgen",
]
[[package]]
name = "smallvec"
version = "1.14.0"
@@ -3285,6 +3764,27 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "supports-color"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
dependencies = [
"is_ci",
]
[[package]]
name = "supports-hyperlinks"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91"
[[package]]
name = "supports-unicode"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
[[package]]
name = "syn"
version = "1.0.109"
@@ -3371,6 +3871,28 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tera"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8004bca281f2d32df3bacd59bc67b312cb4c70cea46cbd79dbe8ac5ed206722"
dependencies = [
"chrono",
"chrono-tz",
"globwalk",
"humansize",
"lazy_static",
"percent-encoding",
"pest",
"pest_derive",
"rand 0.8.5",
"regex",
"serde",
"serde_json",
"slug",
"unicode-segmentation",
]
[[package]]
name = "term"
version = "0.7.0"
@@ -3382,6 +3904,26 @@ dependencies = [
"winapi",
]
[[package]]
name = "terminal_size"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874"
dependencies = [
"rustix 1.1.4",
"windows-sys 0.61.2",
]
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
dependencies = [
"unicode-linebreak",
"unicode-width 0.2.2",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -3497,7 +4039,9 @@ dependencies = [
"bytes",
"libc",
"mio",
"parking_lot 0.12.3",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.6.3",
"tokio-macros",
"windows-sys 0.61.2",
@@ -3741,18 +4285,42 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "ucd-trie"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-segmentation"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
[[package]]
name = "unicode-xid"
version = "0.2.6"
@@ -4089,7 +4657,7 @@ version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
dependencies = [
"windows-core",
"windows-core 0.51.1",
"windows-targets 0.48.5",
]
@@ -4102,6 +4670,41 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.2.1",
"windows-result 0.4.1",
"windows-strings 0.5.1",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.116",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.116",
]
[[package]]
name = "windows-link"
version = "0.1.3"
@@ -4121,8 +4724,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
dependencies = [
"windows-link 0.1.3",
"windows-result",
"windows-strings",
"windows-result 0.3.4",
"windows-strings 0.4.2",
]
[[package]]
@@ -4134,6 +4737,15 @@ dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "windows-strings"
version = "0.4.2"
@@ -4143,6 +4755,15 @@ dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
+3 -4
View File
@@ -1731,7 +1731,10 @@ dependencies = [
"rcgen",
"redis",
"reed-solomon-erasure",
"regex",
"reqwest",
"rsbinder",
"rsbinder-aidl",
"rtnetlink",
"rustls",
"serde",
@@ -1751,12 +1754,8 @@ dependencies = [
name = "mycelium-android"
version = "0.1.0"
dependencies = [
"libc",
"mycelium",
"regex",
"rsbinder",
"rsbinder-aidl",
"tokio",
"tracing",
"tracing-android",
"tracing-subscriber",
+2 -11
View File
@@ -8,19 +8,10 @@ name = "mycelium-android"
path = "src/main.rs"
[dependencies]
mycelium = { path = "../mycelium" }
tokio = { version = "1.50", features = ["rt-multi-thread"] }
rsbinder = { version = "0.6", features = ["android_14_plus"] }
mycelium = { path = "../mycelium", features = ["aidl"] }
rsbinder = { version = "0.6", features = ["android_14"] }
tracing = { version = "0.1", features = ["release_max_level_debug"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
[target.'cfg(target_os = "android")'.dependencies]
tracing-android = "0.2"
libc = "0.2"
[features]
mactunfd = []
[build-dependencies]
rsbinder-aidl = "0.6"
regex = "1"
+3 -16
View File
@@ -1,11 +1,4 @@
// Pull in the AIDL-generated Rust bindings (tech::threefold::mycelium module).
include!(concat!(env!("OUT_DIR"), "/mycelium_aidl.rs"));
mod node;
mod service;
mod service_manager;
use service::MyceliumService;
use mycelium::aidl::{BnMyceliumService, IMyceliumService, MyceliumService};
fn main() {
setup_logging();
@@ -34,14 +27,13 @@ fn main() {
if let Some(path) = &key_file {
let key_data = std::fs::read(path).expect("failed to read key file");
use tech::threefold::mycelium::IMyceliumService::IMyceliumService;
svc.start(&peers, &key_data, false)
.expect("failed to start mycelium node");
}
let binder = tech::threefold::mycelium::IMyceliumService::BnMyceliumService::new_binder(svc);
let binder = BnMyceliumService::new_binder(svc);
service_manager::add_service(
mycelium::aidl::add_service(
"tech.threefold.mycelium.IMyceliumService",
binder.as_binder(),
)
@@ -52,10 +44,6 @@ fn main() {
let _ = rsbinder::ProcessState::join_thread_pool();
}
// ── Logging setup ─────────────────────────────────────────────────────────────
// NOTE: This is copied from mobile.
// TODO: Is this needed, i.e. do we care about capturing logs?
#[cfg(target_os = "android")]
fn setup_logging() {
use tracing::level_filters::LevelFilter;
@@ -73,7 +61,6 @@ fn setup_logging() {
.init();
}
// Convenience when building on linux
#[cfg(not(target_os = "android"))]
fn setup_logging() {
use tracing_subscriber::EnvFilter;
+7
View File
@@ -12,6 +12,7 @@ vendored-openssl = ["openssl/vendored"]
mactunfd = [
"tun/appstore",
] #mactunfd is a flag to specify that macos should provide tun FD instead of tun name
aidl = ["dep:rsbinder", "dep:rsbinder-aidl", "dep:regex"]
[dependencies]
cdn-meta = { git = "https://github.com/threefoldtech/mycelium-cdn-registry", package = "cdn-meta" }
@@ -67,6 +68,7 @@ reed-solomon-erasure = "6.0.0"
hickory-server = "0.26.0"
async-trait = "0.1.89"
hickory-resolver = "0.26.0"
rsbinder = { version = "0.6", features = ["android_14"], optional = true }
[target.'cfg(target_os = "linux")'.dependencies]
rtnetlink = "0.21.0"
nix = { version = "0.31.2", features = ["socket"] }
@@ -83,6 +85,11 @@ wintun = "0.5.1"
[target.'cfg(target_os = "android")'.dependencies]
tun = { git = "https://github.com/LeeSmet/rust-tun", features = ["async"] }
libc = "0.2.180"
[target.'cfg(target_os = "ios")'.dependencies]
tun = { git = "https://github.com/LeeSmet/rust-tun", features = ["async"] }
[build-dependencies]
rsbinder-aidl = { version = "0.6", optional = true }
regex = { version = "1", optional = true }
+14 -20
View File
@@ -1,7 +1,13 @@
fn main() {
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
let output = out_dir.join("mycelium_aidl.rs");
#[cfg(feature = "aidl")]
aidl_codegen();
}
#[cfg(feature = "aidl")]
fn aidl_codegen() {
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
let output = out_dir.join("mycelium_aidl.rs");
rsbinder_aidl::Builder::new()
.source("aidl/tech/threefold/mycelium/PeerInfo.aidl")
.source("aidl/tech/threefold/mycelium/NodeInfo.aidl")
@@ -13,6 +19,7 @@ fn main() {
.output(&output)
.generate()
.unwrap();
patch_async_compat(&output);
let sm_output = out_dir.join("service_manager_a15.rs");
rsbinder_aidl::Builder::new()
@@ -22,31 +29,20 @@ fn main() {
.unwrap();
patch_async_compat(&sm_output);
// rsbinder-aidl 0.6.0 generates async infrastructure that is incompatible with
// async-trait ≥ 0.1.80 on Rust ≥ 1.75 (native AFIT makes async traits non-dyn-compatible).
// We can't pin async-trait < 0.1.80 because mycelium requires ^0.1.89.
patch_async_compat(&output);
println!("cargo:rerun-if-changed=aidl/");
}
/// Fix the generated code so it compiles with modern async-trait.
/// Fix rsbinder-aidl 0.6 generated code for async-trait >= 0.1.80 on Rust >= 1.75.
///
/// `IXxxAsyncService` is annotated `#[async_trait]` with `async fn` methods.
/// With async-trait ≥ 0.1.80 on Rust ≥ 1.75 the macro uses native AFIT, making the
/// trait non-dyn-compatible. The adapter generated by `declare_binder_interface!`
/// requires `&dyn IXxxAsyncService`, so we rewrite every `async fn` to return a
/// `BoxFuture` instead — which is dyn-compatible.
/// The generated `IXxxAsyncService` traits use `async fn` methods annotated with
/// `#[async_trait]`. With modern async-trait the macro uses native AFIT, making
/// the trait non-dyn-compatible. We rewrite `async fn` to return `BoxFuture`.
#[cfg(feature = "aidl")]
fn patch_async_compat(path: &std::path::Path) {
let src = std::fs::read_to_string(path).expect("read generated AIDL file");
// Step 1 — Strip #[async_trait] from the AsyncService trait.
let patched = src.replace("#[::async_trait::async_trait]\n", "");
// Step 2 — Rewrite every `async fn r#name(params) -> RetType;` found in the file
// (only IXxxAsyncService uses async fn in rsbinder-aidl generated code).
// Each `&` in the parameter list gets a `'a` lifetime; the return type is wrapped
// in BoxFuture<'a, _>. Method names keep the `r#` raw-identifier prefix.
let async_fn_re =
regex::Regex::new(r"(?m)^(\s+)async fn (r#\w+)\(([^)]+)\)\s*->\s*([^;]+);$").unwrap();
@@ -54,8 +50,6 @@ fn patch_async_compat(path: &std::path::Path) {
.replace_all(&patched, |caps: &regex::Captures| {
let indent = &caps[1];
let name = &caps[2];
// Add 'a lifetime to every reference parameter, but leave &self untouched.
// Workaround: replace &self with a unique marker before adding 'a, then restore it.
let params = caps[3]
.replace("&self", "\x00SELF\x00")
.replace('&', "&'a ")
+48
View File
@@ -0,0 +1,48 @@
//! Conversions between mycelium core types and AIDL-generated parcelables.
use crate::peer_manager::PeerStats;
use crate::routing_table::RouteEntry;
use super::tech::threefold::mycelium::PacketStatEntry::PacketStatEntry;
use super::tech::threefold::mycelium::PeerInfo::PeerInfo;
use super::tech::threefold::mycelium::Route::Route;
impl From<PeerStats> for PeerInfo {
fn from(p: PeerStats) -> Self {
PeerInfo {
protocol: p.endpoint.proto().to_string(),
address: p.endpoint.address().to_string(),
peerType: p.pt.to_string(),
connectionState: p.connection_state.to_string(),
rxBytes: p.rx_bytes as i64,
txBytes: p.tx_bytes as i64,
discoveredSeconds: p.discovered as i64,
lastConnectedSeconds: p.last_connected.map(|v| v as i64).unwrap_or(-1),
}
}
}
impl From<RouteEntry> for Route {
fn from(r: RouteEntry) -> Self {
Route {
subnet: r.source().subnet().to_string(),
nextHop: r.neighbour().connection_identifier().clone(),
metric: if r.metric().is_infinite() {
-1
} else {
u16::from(r.metric()) as i64
},
seqno: u16::from(r.seqno()) as i32,
}
}
}
impl From<crate::router::PacketStatEntry> for PacketStatEntry {
fn from(e: crate::router::PacketStatEntry) -> Self {
PacketStatEntry {
ip: e.ip.to_string(),
packetCount: e.packet_count as i64,
byteCount: e.byte_count as i64,
}
}
}
+19
View File
@@ -0,0 +1,19 @@
//! Android AIDL (Binder IPC) interface for the mycelium node.
//!
//! This module is only compiled when the `aidl` feature is enabled. It provides
//! [`MyceliumService`] which implements the `IMyceliumService` AIDL interface,
//! and [`add_service`] to register the service with Android's ServiceManager.
// Pull in the AIDL-generated Rust bindings (tech::threefold::mycelium module).
include!(concat!(env!("OUT_DIR"), "/mycelium_aidl.rs"));
mod conversions;
mod service;
mod service_manager;
pub use service::MyceliumService;
pub use service_manager::add_service;
// Re-export the generated BnMyceliumService for the binary to use.
pub use tech::threefold::mycelium::IMyceliumService::BnMyceliumService;
pub use tech::threefold::mycelium::IMyceliumService::IMyceliumService;
@@ -1,19 +1,23 @@
//! Implementation of the `IMyceliumService` AIDL interface.
use std::net::{IpAddr, SocketAddr};
use std::sync::Mutex;
use rsbinder::StatusCode;
use tracing::{error, info, warn};
use crate::node::{parse_proxy_remote, peer_stats_to_aidl, NodeHandle, DEFAULT_SOCKS_PORT};
use crate::tech::threefold::mycelium::IMyceliumService::IMyceliumService;
use crate::tech::threefold::mycelium::NodeInfo::NodeInfo;
use crate::tech::threefold::mycelium::PacketStatEntry::PacketStatEntry;
use crate::tech::threefold::mycelium::PacketStats::PacketStats;
use crate::tech::threefold::mycelium::PeerInfo::PeerInfo;
use crate::tech::threefold::mycelium::QueriedSubnet::QueriedSubnet;
use crate::tech::threefold::mycelium::Route::Route;
use crate::metrics::NoMetrics;
use crate::node_handle::{parse_proxy_remote, NodeHandle, DEFAULT_SOCKS_PORT};
use crate::peer_manager::PeerDiscoveryMode;
use crate::{crypto, Config};
// ── Service struct ─────────────────────────────────────────────────────────────
use super::tech::threefold::mycelium::IMyceliumService::IMyceliumService;
use super::tech::threefold::mycelium::NodeInfo::NodeInfo;
use super::tech::threefold::mycelium::PacketStatEntry::PacketStatEntry;
use super::tech::threefold::mycelium::PacketStats::PacketStats;
use super::tech::threefold::mycelium::PeerInfo::PeerInfo;
use super::tech::threefold::mycelium::QueriedSubnet::QueriedSubnet;
use super::tech::threefold::mycelium::Route::Route;
/// Implements the `IMyceliumService` AIDL interface.
///
@@ -21,15 +25,20 @@ use crate::tech::threefold::mycelium::Route::Route;
/// answers immediately (pure computation) or uses `rt_handle.block_on` to
/// drive an async operation against the running mycelium node.
pub struct MyceliumService {
/// Running node handle, present once `start()` has been called.
handle: Mutex<Option<NodeHandle>>,
}
impl Default for MyceliumService {
fn default() -> Self {
MyceliumService {
handle: Mutex::new(None),
}
}
}
impl MyceliumService {
pub fn new() -> Self {
MyceliumService {
handle: Mutex::new(None),
}
Self::default()
}
}
@@ -49,7 +58,43 @@ impl IMyceliumService for MyceliumService {
info!("starting mycelium node, {} peers", peers.len());
match NodeHandle::start(peers.to_vec(), key, enable_dns) {
let endpoints = peers.iter().filter_map(|p| p.parse().ok()).collect();
#[cfg(target_os = "android")]
let tun_fd = crate::node_handle::create_tun_fd("tun0").map_err(|e| {
error!("Failed to create TUN fd: {e}");
rsbinder::Status::from(StatusCode::Unknown)
})?;
let config = Config {
node_key: crypto::SecretKey::from(key),
peers: endpoints,
no_tun: false,
#[cfg(any(
target_os = "linux",
all(target_os = "macos", not(feature = "mactunfd")),
target_os = "windows"
))]
tun_name: "tun0".to_string(),
#[cfg(any(
target_os = "android",
target_os = "ios",
all(target_os = "macos", feature = "mactunfd"),
))]
tun_fd: Some(tun_fd),
tcp_listen_port: 9651,
quic_listen_port: Some(9651),
peer_discovery_port: 9650,
peer_discovery_mode: PeerDiscoveryMode::Disabled,
metrics: NoMetrics,
private_network_config: None,
firewall_mark: None,
update_workers: 1,
cdn_cache: None,
enable_dns,
};
match NodeHandle::start(config) {
Ok(h) => {
*self.handle.lock().unwrap() = Some(h);
Ok(true)
@@ -125,7 +170,7 @@ impl IMyceliumService for MyceliumService {
.await
.peer_info()
.into_iter()
.map(peer_stats_to_aidl)
.map(PeerInfo::from)
.collect())
})
}
@@ -136,7 +181,7 @@ impl IMyceliumService for MyceliumService {
.as_ref()
.ok_or_else(|| rsbinder::Status::from(StatusCode::InvalidOperation))?;
let endpoint = endpoint
.parse::<mycelium::endpoint::Endpoint>()
.parse::<crate::endpoint::Endpoint>()
.map_err(|_| rsbinder::Status::from(StatusCode::BadValue))?;
h.rt()
.block_on(async { Ok(h.node().lock().await.add_peer(endpoint).is_ok()) })
@@ -148,7 +193,7 @@ impl IMyceliumService for MyceliumService {
.as_ref()
.ok_or_else(|| rsbinder::Status::from(StatusCode::InvalidOperation))?;
let endpoint = endpoint
.parse::<mycelium::endpoint::Endpoint>()
.parse::<crate::endpoint::Endpoint>()
.map_err(|_| rsbinder::Status::from(StatusCode::BadValue))?;
h.rt()
.block_on(async { Ok(h.node().lock().await.remove_peer(endpoint).is_ok()) })
@@ -165,16 +210,7 @@ impl IMyceliumService for MyceliumService {
.await
.selected_routes()
.into_iter()
.map(|r| Route {
subnet: r.source().subnet().to_string(),
nextHop: r.neighbour().connection_identifier().clone(),
metric: if r.metric().is_infinite() {
-1
} else {
u16::from(r.metric()) as i64
},
seqno: u16::from(r.seqno()) as i32,
})
.map(Route::from)
.collect())
})
}
@@ -190,16 +226,7 @@ impl IMyceliumService for MyceliumService {
.await
.fallback_routes()
.into_iter()
.map(|r| Route {
subnet: r.source().subnet().to_string(),
nextHop: r.neighbour().connection_identifier().clone(),
metric: if r.metric().is_infinite() {
-1
} else {
u16::from(r.metric()) as i64
},
seqno: u16::from(r.seqno()) as i32,
})
.map(Route::from)
.collect())
})
}
@@ -233,40 +260,22 @@ impl IMyceliumService for MyceliumService {
h.rt().block_on(async {
let stats = h.node().lock().await.packet_statistics();
Ok(PacketStats {
bySource: stats
.by_source
.into_iter()
.map(|e| PacketStatEntry {
ip: e.ip.to_string(),
packetCount: e.packet_count as i64,
byteCount: e.byte_count as i64,
})
.collect(),
byDestination: stats
.by_destination
.into_iter()
.map(|e| PacketStatEntry {
ip: e.ip.to_string(),
packetCount: e.packet_count as i64,
byteCount: e.byte_count as i64,
})
.collect(),
bySource: stats.by_source.into_iter().map(PacketStatEntry::from).collect(),
byDestination: stats.by_destination.into_iter().map(PacketStatEntry::from).collect(),
})
})
}
fn generateSecretKey(&self) -> rsbinder::status::Result<Vec<u8>> {
Ok(mycelium::crypto::SecretKey::new().as_bytes().to_vec())
Ok(crypto::SecretKey::new().as_bytes().to_vec())
}
fn addressFromSecretKey(&self, key: &[u8]) -> rsbinder::status::Result<String> {
let arr: [u8; 32] = key
.try_into()
.map_err(|_| rsbinder::Status::from(StatusCode::BadValue))?;
let secret = mycelium::crypto::SecretKey::from(arr);
Ok(mycelium::crypto::PublicKey::from(&secret)
.address()
.to_string())
let secret = crypto::SecretKey::from(arr);
Ok(crypto::PublicKey::from(&secret).address().to_string())
}
fn startProxyProbe(&self) -> rsbinder::status::Result<bool> {
@@ -320,7 +329,6 @@ impl IMyceliumService for MyceliumService {
h.rt().block_on(async {
let future = h.node().lock().await.connect_proxy(remote_addr);
// MutexGuard released before await
match future.await {
Ok(addr) => Ok(addr.to_string()),
Err(e) => {
@@ -1,3 +1,10 @@
//! Android 15 ServiceManager registration workaround.
//!
//! rsbinder 0.6 doesn't have a correct IServiceManager AIDL for Android 15
//! (API 35), which inserted `getService2` between `getService` and
//! `checkService`, shifting transaction codes. We generate our own bindings
//! from a corrected AIDL file.
include!(concat!(env!("OUT_DIR"), "/service_manager_a15.rs"));
use android::os::IServiceManager::{BpServiceManager, IServiceManager};
@@ -5,6 +12,7 @@ use rsbinder::{ProcessState, Proxy, SIBinder};
const DUMP_FLAG_PRIORITY_DEFAULT: i32 = 1 << 3;
/// Register a Binder service with Android's ServiceManager.
pub fn add_service(name: &str, binder: SIBinder) -> Result<(), rsbinder::status::Status> {
let context = ProcessState::as_self()
.context_object()
+3
View File
@@ -49,6 +49,9 @@ mod rr_cache;
mod seqno_cache;
mod sequence_number;
mod source_table;
#[cfg(feature = "aidl")]
pub mod aidl;
pub mod node_handle;
pub mod subnet;
pub mod task;
mod tun;
+5
View File
@@ -233,3 +233,8 @@ pub trait Metrics {
#[inline]
fn router_incoming_packet_queue_full_subnet(&self) {}
}
/// A no-op [`Metrics`] implementation that discards all metrics.
#[derive(Clone)]
pub struct NoMetrics;
impl Metrics for NoMetrics {}
@@ -1,16 +1,27 @@
//! Synchronous wrapper around a [`Node`] running on a background Tokio runtime.
//!
//! This module provides [`NodeHandle`], which spawns a mycelium node in a
//! dedicated thread with its own Tokio runtime. All access goes through the
//! handle, which exposes blocking methods suitable for use from non-async
//! contexts (AIDL Binder threads, C FFI, etc.).
use std::net::SocketAddr;
use std::sync::Arc;
use mycelium::peer_manager::{PeerDiscoveryMode, PeerStats};
use mycelium::{crypto, metrics::Metrics, Config, Node};
use tokio::sync::Mutex;
use tracing::{error, info};
// ── Error type ────────────────────────────────────────────────────────────────
use crate::metrics::NoMetrics;
use crate::{Config, Node};
// ── Error type ──────────────────────────────────────────────────────────────
/// Errors that can occur when starting a [`NodeHandle`].
#[derive(Debug)]
pub enum NodeError {
/// The background thread panicked or failed to start the Tokio runtime.
ThreadPanic,
/// The mycelium [`Node`] could not be created.
NodeCreate(String),
}
@@ -25,22 +36,13 @@ impl std::fmt::Display for NodeError {
impl std::error::Error for NodeError {}
// ── NoMetrics ─────────────────────────────────────────────────────────────────
#[derive(Clone)]
pub struct NoMetrics;
impl Metrics for NoMetrics {}
// ── TUN setup (Android only) ──────────────────────────────────────────────────
// ── TUN setup (Android only) ────────────────────────────────────────────────
/// On Android the `tun` crate expects an already-opened file descriptor.
/// This function opens `/dev/tun`, configures the interface with TUNSETIFF,
/// and returns the raw fd. Requires `CAP_NET_ADMIN`.
///
/// NOTE: If we continue with this approach, it's better to change the TUN code inside mycelium to do this, similar to linux.
#[cfg(target_os = "android")]
fn create_tun_fd(tun_name: &str) -> Result<i32, std::io::Error> {
// TUNSETIFF = _IOW('T', 202, int) = 0x400454ca
pub fn create_tun_fd(tun_name: &str) -> Result<i32, std::io::Error> {
const TUNSETIFF: libc::c_ulong = 0x400454ca;
const IFF_TUN: libc::c_short = 0x0001;
const IFF_NO_PI: libc::c_short = 0x1000;
@@ -50,10 +52,9 @@ fn create_tun_fd(tun_name: &str) -> Result<i32, std::io::Error> {
return Err(std::io::Error::last_os_error());
}
// struct ifreq: char[16] name, then union starting with short flags
let mut ifr = [0u8; 40];
let name_bytes = tun_name.as_bytes();
let len = name_bytes.len().min(15); // IFNAMSIZ - 1, leave room for null
let len = name_bytes.len().min(15);
ifr[..len].copy_from_slice(&name_bytes[..len]);
let flags: i16 = IFF_TUN | IFF_NO_PI;
ifr[16] = (flags & 0xff) as u8;
@@ -69,10 +70,11 @@ fn create_tun_fd(tun_name: &str) -> Result<i32, std::io::Error> {
Ok(fd)
}
// ── NodeHandle ─────────────────────────────────────────────────────────────────
// ── NodeHandle ──────────────────────────────────────────────────────────────
/// Handle to a running mycelium node. Holds a reference to the node for direct
/// method calls and the Tokio runtime handle to drive them from Binder threads.
/// method calls and the Tokio runtime handle to drive them from non-async
/// threads (e.g. Binder threads, C FFI callbacks).
pub struct NodeHandle {
node: Arc<Mutex<Node<NoMetrics>>>,
rt_handle: tokio::runtime::Handle,
@@ -81,12 +83,10 @@ pub struct NodeHandle {
impl NodeHandle {
/// Spawn the Tokio runtime and mycelium node in a background thread.
///
/// Blocks the calling thread until the node is ready (or fails to start).
pub fn start(
peers: Vec<String>,
priv_key: [u8; 32],
enable_dns: bool,
) -> Result<Self, NodeError> {
/// The caller provides a fully constructed [`Config`].
pub fn start(config: Config<NoMetrics>) -> Result<Self, NodeError> {
let (result_tx, result_rx) = std::sync::mpsc::sync_channel(1);
let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>();
@@ -99,8 +99,6 @@ impl NodeHandle {
Ok(rt) => rt,
Err(e) => {
error!("Failed to build Tokio runtime: {e}");
// Can't send NodeCreate error here since we don't have the box yet,
// but ThreadPanic is close enough for a runtime build failure.
let _ = result_tx.send(Err(NodeError::ThreadPanic));
return;
}
@@ -109,49 +107,6 @@ impl NodeHandle {
let handle = rt.handle().clone();
rt.block_on(async move {
let endpoints = peers
.iter()
.filter_map(|p| p.parse().ok())
.collect::<Vec<_>>();
#[cfg(target_os = "android")]
let tun_fd = match create_tun_fd("tun0") {
Ok(fd) => fd,
Err(e) => {
error!("Failed to create TUN fd: {e}");
let _ = result_tx.send(Err(NodeError::NodeCreate(e.to_string())));
return;
}
};
let config = Config {
node_key: crypto::SecretKey::from(priv_key),
peers: endpoints,
no_tun: false,
#[cfg(any(
target_os = "linux",
all(target_os = "macos", not(feature = "mactunfd")),
target_os = "windows"
))]
tun_name: "tun0".to_string(),
#[cfg(any(
target_os = "android",
target_os = "ios",
all(target_os = "macos", feature = "mactunfd"),
))]
tun_fd: Some(tun_fd),
tcp_listen_port: 9651,
quic_listen_port: Some(9651),
peer_discovery_port: 9650,
peer_discovery_mode: PeerDiscoveryMode::Disabled,
metrics: NoMetrics,
private_network_config: None,
firewall_mark: None,
update_workers: 1,
cdn_cache: None,
enable_dns,
};
match Node::new(config).await {
Err(e) => {
error!("Failed to create node: {e}");
@@ -161,7 +116,6 @@ impl NodeHandle {
info!("mycelium node started");
let node = Arc::new(Mutex::new(node));
let _ = result_tx.send(Ok((Arc::clone(&node), handle)));
// Keep the runtime alive until stop() is called.
let _ = shutdown_rx.await;
info!("mycelium node stopped");
}
@@ -186,38 +140,27 @@ impl NodeHandle {
}
}
/// Returns `true` if the node has not been stopped.
pub fn is_running(&self) -> bool {
self.shutdown_tx.is_some()
}
/// Reference to the underlying [`Node`], wrapped in an async [`Mutex`].
pub fn node(&self) -> &Arc<Mutex<Node<NoMetrics>>> {
&self.node
}
/// Handle to the background Tokio runtime. Use this with
/// [`block_on`](tokio::runtime::Handle::block_on) to drive async node
/// methods from synchronous code.
pub fn rt(&self) -> &tokio::runtime::Handle {
&self.rt_handle
}
}
// ── Helpers ───────────────────────────────────────────────────────────────────
// ── Helpers ─────────────────────────────────────────────────────────────────
/// Convert a [`PeerStats`] to the AIDL-generated `PeerInfo` parcelable.
// rsbinder-aidl generates a sub-module with the same name as the parcelable,
// so the type is PeerInfo::PeerInfo.
pub fn peer_stats_to_aidl(p: PeerStats) -> crate::tech::threefold::mycelium::PeerInfo::PeerInfo {
crate::tech::threefold::mycelium::PeerInfo::PeerInfo {
protocol: p.endpoint.proto().to_string(),
address: p.endpoint.address().to_string(),
peerType: p.pt.to_string(),
connectionState: p.connection_state.to_string(),
rxBytes: p.rx_bytes as i64,
txBytes: p.tx_bytes as i64,
discoveredSeconds: p.discovered as i64,
lastConnectedSeconds: p.last_connected.map(|v| v as i64).unwrap_or(-1),
}
}
/// Parse a proxy address string ("ip:port") into a [`SocketAddr`].
/// Parse a proxy address string (`"ip:port"`) into a [`SocketAddr`].
/// Returns `None` for an empty string (auto-select).
pub fn parse_proxy_remote(remote: &str) -> Result<Option<SocketAddr>, String> {
if remote.is_empty() {