Move from magiclip project

Signed-off-by: Walker Crouse <walker.crouse@coop.co.uk>
This commit is contained in:
Walker Crouse 2020-09-24 18:03:10 -04:00
parent 5a1b5a3505
commit 55cbcfe154
33 changed files with 2964 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/target

506
Cargo.lock generated Normal file
View File

@ -0,0 +1,506 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "avahi-sys"
version = "0.9.0"
dependencies = [
"bindgen",
"libc",
]
[[package]]
name = "bindgen"
version = "0.55.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b13ce559e6433d360c26305643803cb52cfbabbc2b9c47ce04a58493dfb443"
dependencies = [
"bitflags",
"cexpr",
"cfg-if",
"clang-sys",
"clap",
"env_logger",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bonjour-sys"
version = "0.1.0"
dependencies = [
"bindgen",
"libc",
]
[[package]]
name = "cexpr"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clang-sys"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9da1484c6a890e374ca5086062d4847e0a2c1e5eba9afa5d48c09e8eb39b2519"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim 0.8.0",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "darling"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.9.3",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "derive-getters"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c5905670fd9c320154f3a4a01c9e609733cd7b753f3c58777ab7d5ce26686b3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive_builder"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
dependencies = [
"darling",
"derive_builder_core",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive_builder_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "hermit-abi"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
[[package]]
name = "libloading"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2443d8f0478b16759158b2f66d525991a05491138bc05814ef52a250148ef4f9"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"memchr",
"version_check",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "proc-macro2"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "serde"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "syn"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
dependencies = [
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "zeroconf"
version = "0.1.0"
dependencies = [
"avahi-sys",
"bonjour-sys",
"derive-getters",
"derive_builder",
"libc",
"log",
"serde",
"zeroconf-macros",
]
[[package]]
name = "zeroconf-macros"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]

5
Cargo.toml Normal file
View File

@ -0,0 +1,5 @@
[workspace]
members = [
"zeroconf",
"zeroconf-macros",
]

89
README.md Normal file
View File

@ -0,0 +1,89 @@
# zeroconf
`zeroconf` is a cross-platform library that wraps underlying [ZeroConf/mDNS] implementations
such as [Bonjour] or [Avahi], providing an easy and idiomatic way to both register and
browse services.
[ZeroConf/mDNS]: https://en.wikipedia.org/wiki/Zero-configuration_networking
[Bonjour]: https://en.wikipedia.org/wiki/Bonjour_(software)
[Avahi]: https://en.wikipedia.org/wiki/Avahi_(software)
## Prerequisites
```bash
$ sudo apt install xorg-dev libxcb-shape0-dev libxcb-xfixes0-dev clang
```
## Examples
## Register a service
When registering a service, you may optionally pass a "context" to pass state through the
callback. The only requirement is that this context implements the [`Any`] trait, which most
types will automatically. See [`MdnsService`] for more information about contexts.
```
use std::any::Any;
use std::sync::{Arc, Mutex};
use zeroconf::{MdnsService, ServiceRegistration};
#[derive(Default, Debug)]
pub struct Context {
service_name: String,
}
fn main() {
let mut service = MdnsService::new("_http._tcp", 8080);
let context: Arc<Mutex<Context>> = Arc::default();
service.set_registered_callback(Box::new(on_service_registered));
service.set_context(Box::new(context));
// blocks current thread, must keep-alive to keep service active
service.start().unwrap();
}
fn on_service_registered(service: ServiceRegistration, context: Option<Arc<dyn Any>>) {
println!("Service registered: {:?}", service);
let context = context
.as_ref()
.unwrap()
.downcast_ref::<Arc<Mutex<Context>>>()
.unwrap()
.clone();
context.lock().unwrap().service_name = service.name().clone();
println!("Context: {:?}", context);
// ...
}
```
## Browsing services
```
use std::any::Any;
use std::sync::Arc;
use zeroconf::{MdnsBrowser, ServiceDiscovery};
fn main() {
let mut browser = MdnsBrowser::new("_http._tcp");
browser.set_service_discovered_callback(Box::new(on_service_discovered));
// blocks current thread, must keep-alive to keep browser active
browser.start().unwrap()
}
fn on_service_discovered(service: ServiceDiscovery, _context: Option<Arc<dyn Any>>) {
println!("Service discovered: {:?}", &service);
// ...
}
```
## TODO
## Caveats

520
examples/Cargo.lock generated Normal file
View File

@ -0,0 +1,520 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "avahi-sys"
version = "0.9.0"
dependencies = [
"bindgen",
"libc",
]
[[package]]
name = "bindgen"
version = "0.55.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b13ce559e6433d360c26305643803cb52cfbabbc2b9c47ce04a58493dfb443"
dependencies = [
"bitflags",
"cexpr",
"cfg-if",
"clang-sys",
"clap",
"env_logger",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bonjour-sys"
version = "0.1.0"
dependencies = [
"bindgen",
"libc",
]
[[package]]
name = "cexpr"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clang-sys"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9da1484c6a890e374ca5086062d4847e0a2c1e5eba9afa5d48c09e8eb39b2519"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim 0.8.0",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "darling"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.9.3",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "derive-getters"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c5905670fd9c320154f3a4a01c9e609733cd7b753f3c58777ab7d5ce26686b3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive_builder"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
dependencies = [
"darling",
"derive_builder_core",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive_builder_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "hermit-abi"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
[[package]]
name = "libloading"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2443d8f0478b16759158b2f66d525991a05491138bc05814ef52a250148ef4f9"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"memchr",
"version_check",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "proc-macro2"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "serde"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "syn"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
dependencies = [
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "zeroconf"
version = "0.1.0"
dependencies = [
"avahi-sys",
"bonjour-sys",
"derive-getters",
"derive_builder",
"libc",
"log",
"serde",
"zeroconf-macros",
]
[[package]]
name = "zeroconf-browser-example"
version = "0.1.0"
dependencies = [
"zeroconf",
]
[[package]]
name = "zeroconf-macros"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "zeroconf-service-example"
version = "0.1.0"
dependencies = [
"zeroconf",
]

5
examples/Cargo.toml Normal file
View File

@ -0,0 +1,5 @@
[workspace]
members = [
"browser",
"service",
]

View File

@ -0,0 +1,8 @@
[package]
name = "zeroconf-browser-example"
version = "0.1.0"
authors = ["Walker Crouse <walkercrouse@hotmail.com>"]
edition = "2018"
[dependencies]
zeroconf = { path = "../../zeroconf" }

View File

@ -0,0 +1,18 @@
use std::any::Any;
use std::sync::Arc;
use zeroconf::{MdnsBrowser, ServiceDiscovery};
fn main() {
let mut browser = MdnsBrowser::new("_http._tcp");
browser.set_service_discovered_callback(Box::new(on_service_discovered));
// blocks current thread, must keep-alive to keep browser active
browser.start().unwrap()
}
fn on_service_discovered(service: ServiceDiscovery, _context: Option<Arc<dyn Any>>) {
println!("Service discovered: {:?}", &service);
// ...
}

View File

@ -0,0 +1,8 @@
[package]
name = "zeroconf-service-example"
version = "0.1.0"
authors = ["Walker Crouse <walkercrouse@hotmail.com>"]
edition = "2018"
[dependencies]
zeroconf = { path = "../../zeroconf" }

View File

@ -0,0 +1,36 @@
use std::any::Any;
use std::sync::{Arc, Mutex};
use zeroconf::{MdnsService, ServiceRegistration};
#[derive(Default, Debug)]
pub struct Context {
service_name: String,
}
fn main() {
let mut service = MdnsService::new("_http._tcp", 8080);
let context: Arc<Mutex<Context>> = Arc::default();
service.set_registered_callback(Box::new(on_service_registered));
service.set_context(Box::new(context));
// blocks current thread, must keep-alive to keep service active
service.start().unwrap();
}
fn on_service_registered(service: ServiceRegistration, context: Option<Arc<dyn Any>>) {
println!("Service registered: {:?}", service);
let context = context
.as_ref()
.unwrap()
.downcast_ref::<Arc<Mutex<Context>>>()
.unwrap()
.clone();
context.lock().unwrap().service_name = service.name().clone();
println!("Context: {:?}", context);
// ...
}

View File

@ -0,0 +1,12 @@
[package]
name = "zeroconf-macros"
version = "0.1.0"
authors = ["Walker Crouse <walkercrouse@hotmail.com>"]
edition = "2018"
[lib]
proc-macro = true
[dependencies]
syn = "1.0.41"
quote = "1.0.7"

View File

@ -0,0 +1,70 @@
extern crate proc_macro;
use crate::proc_macro::TokenStream;
use quote::quote;
use syn::{self, DeriveInput, Ident};
#[proc_macro_derive(FromRaw)]
pub fn from_raw_macro_derive(input: TokenStream) -> TokenStream {
impl_from_raw(&syn::parse(input).unwrap())
}
fn impl_from_raw(ast: &DeriveInput) -> TokenStream {
let name = &ast.ident;
let generics = &ast.generics;
let gen = quote! {
impl #generics crate::ffi::FromRaw<#name #generics> for #name #generics {}
};
gen.into()
}
#[proc_macro_derive(CloneRaw)]
pub fn clone_raw_macro_derive(input: TokenStream) -> TokenStream {
impl_clone_raw(&syn::parse(input).unwrap())
}
fn impl_clone_raw(ast: &DeriveInput) -> TokenStream {
let name = &ast.ident;
let generics = &ast.generics;
let gen = quote! {
impl #generics crate::ffi::CloneRaw<#name #generics> for #name #generics {}
};
gen.into()
}
#[proc_macro_derive(AsRaw)]
pub fn as_raw_macro_derive(input: TokenStream) -> TokenStream {
impl_as_raw(&syn::parse(input).unwrap())
}
fn impl_as_raw(ast: &DeriveInput) -> TokenStream {
let name = &ast.ident;
let generics = &ast.generics;
let gen = quote! {
impl #generics crate::ffi::AsRaw for #name #generics {}
};
gen.into()
}
#[proc_macro_derive(BuilderDelegate)]
pub fn builder_delegate_macro_derive(input: TokenStream) -> TokenStream {
impl_builder_delegate(&syn::parse(input).unwrap())
}
fn impl_builder_delegate(ast: &DeriveInput) -> TokenStream {
let name = &ast.ident;
let builder: Ident = syn::parse_str(&format!("{}Builder", name)).unwrap();
let generics = &ast.generics;
let gen = quote! {
impl #generics crate::builder::BuilderDelegate<#builder #generics> for #name #generics {}
};
gen.into()
}

19
zeroconf/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "zeroconf"
version = "0.1.0"
authors = ["Walker Crouse <walkercrouse@hotmail.com>"]
edition = "2018"
[dependencies]
serde = { version = "1.0.116", features = ["derive"] }
derive-getters = "0.2.0"
libc = "*"
derive_builder = "0.9.0"
zeroconf-macros = { path = "../zeroconf-macros" }
log = "0.4.11"
[target.'cfg(unix)'.dependencies]
avahi-sys = { path = "../../avahi-sys" }
[target.'cfg(target_os = "macos")'.dependencies]
bonjour-sys = { path = "../../bonjour-sys" }

9
zeroconf/src/builder.rs Normal file
View File

@ -0,0 +1,9 @@
//! Provides builder related helpers
/// Implements a `builder()` function for the specified type
pub trait BuilderDelegate<T: Default> {
/// Initializes a new default builder of type `T`
fn builder() -> T {
T::default()
}
}

25
zeroconf/src/discovery.rs Normal file
View File

@ -0,0 +1,25 @@
use std::any::Any;
use std::sync::Arc;
/// Callback invoked from [`MdnsBrowser`] once a service has been discovered and resolved.
///
/// # Arguments
/// * `discovered_service` - The service that was disovered
/// * `context` - The optional user context passed through using [`MdnsBrowser::set_context()`]
///
/// [`MdnsBrowser`]: struct.MdnsBrowser.html
/// [`MdnsBrowser::set_context()`]: struct.MdnsBrowser.html#method.set_context
pub type ServiceDiscoveredCallback = dyn Fn(ServiceDiscovery, Option<Arc<dyn Any>>);
/// Represents a service that has been discovered by a [`MdnsBrowser`].
///
/// [`MdnsBrowser`]: struct.MdnsBrowser.html
#[derive(Debug, Getters, Builder, BuilderDelegate, Serialize, Deserialize)]
pub struct ServiceDiscovery {
name: String,
kind: String,
domain: String,
host_name: String,
address: String,
port: u16,
}

62
zeroconf/src/ffi.rs Normal file
View File

@ -0,0 +1,62 @@
//! Utilities related to FFI bindings
use libc::c_void;
/// Helper trait to convert a raw `*mut c_void` to it's rust type
pub trait FromRaw<T> {
/// Converts the specified `*mut c_void` to a `&'a mut T`.
///
/// # Unsafe
/// This function is unsafe due to the dereference of the specified raw pointer.
unsafe fn from_raw<'a>(raw: *mut c_void) -> &'a mut T {
&mut *(raw as *mut T)
}
}
/// Helper trait to convert and clone a raw `*mut c_void` to it's rust type
pub trait CloneRaw<T: FromRaw<T> + Clone> {
/// Converts and clones the specified `*mut c_void` to a `Box<T>`.
///
/// # Unsafe
/// This function is unsafe due to a call to the unsafe function [`FromRaw::from_raw()`].
///
/// [`FromRaw::from_raw()`]: trait.FromRaw.html#method.from_raw
unsafe fn clone_raw<'a>(raw: *mut c_void) -> Box<T> {
Box::new(T::from_raw(raw).clone())
}
}
/// Helper trait to convert self to a raw `*mut c_void`
pub trait AsRaw {
/// Converts self to a raw `*mut c_void` by cast.
fn as_raw(&mut self) -> *mut c_void {
self as *mut _ as *mut c_void
}
}
pub mod cstr {
//! FFI utilities related to c-strings
use libc::c_char;
use std::ffi::CStr;
/// Returns the specified `*const c_char` as a `&'a str`. Ownership is not taken.
///
/// # Unsafe
/// This function is unsafe due to a call to the unsafe function [`CStr::from_ptr()`].
///
/// [`CStr::from_ptr()`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.from_ptr
pub unsafe fn raw_to_str<'a>(s: *const c_char) -> &'a str {
CStr::from_ptr(s).to_str().unwrap()
}
/// Copies the specified `*const c_char` into a `String`.
///
/// # Unsafe
/// This function is unsafe due to a call to the unsafe function [`raw_to_str()`].
///
/// [`raw_to_str()`]: fn.raw_to_str.html
pub unsafe fn copy_raw(s: *const c_char) -> String {
String::from(raw_to_str(s))
}
}

128
zeroconf/src/lib.rs Normal file
View File

@ -0,0 +1,128 @@
//! `zeroconf` is a cross-platform library that wraps underlying [ZeroConf/mDNS] implementations
//! such as [Bonjour] or [Avahi], providing an easy and idiomatic way to both register and
//! browse services.
//!
//! This crate provides the cross-platform [`MdnsService`] and [`MdnsBrowser`] available for each
//! supported platform as well as platform-specific modules for lower-level access to the mDNS
//! implementation should that be necessary.
//!
//! Most users of this crate need only [`MdnsService`] and [`MdnsBrowser`].
//!
//! # Examples
//!
//! ## Register a service
//!
//! When registering a service, you may optionally pass a "context" to pass state through the
//! callback. The only requirement is that this context implements the [`Any`] trait, which most
//! types will automatically. See [`MdnsService`] for more information about contexts.
//!
//! ```
//! use std::any::Any;
//! use std::sync::{Arc, Mutex};
//! use zeroconf::{MdnsService, ServiceRegistration};
//!
//! #[derive(Default, Debug)]
//! pub struct Context {
//! service_name: String,
//! }
//!
//! fn main() {
//! let mut service = MdnsService::new("_http._tcp", 8080);
//! let context: Arc<Mutex<Context>> = Arc::default();
//!
//! service.set_registered_callback(Box::new(on_service_registered));
//! service.set_context(Box::new(context));
//!
//! // blocks current thread, must keep-alive to keep service active
//! service.start().unwrap();
//! }
//!
//! fn on_service_registered(service: ServiceRegistration, context: Option<Arc<dyn Any>>) {
//! println!("Service registered: {:?}", service);
//!
//! let context = context
//! .as_ref()
//! .unwrap()
//! .downcast_ref::<Arc<Mutex<Context>>>()
//! .unwrap()
//! .clone();
//!
//! context.lock().unwrap().service_name = service.name().clone();
//!
//! println!("Context: {:?}", context);
//!
//! // ...
//! }
//! ```
//!
//! ## Browsing services
//!
//! ```
//! use std::any::Any;
//! use std::sync::Arc;
//! use zeroconf::{MdnsBrowser, ServiceDiscovery};
//!
//! fn main() {
//! let mut browser = MdnsBrowser::new("_http._tcp");
//!
//! browser.set_service_discovered_callback(Box::new(on_service_discovered));
//!
//! // blocks current thread, must keep-alive to keep browser active
//! browser.start().unwrap()
//! }
//!
//! fn on_service_discovered(service: ServiceDiscovery, _context: Option<Arc<dyn Any>>) {
//! println!("Service discovered: {:?}", &service);
//!
//! // ...
//! }
//! ```
//! [ZeroConf/mDNS]: https://en.wikipedia.org/wiki/Zero-configuration_networking
//! [Bonjour]: https://en.wikipedia.org/wiki/Bonjour_(software)
//! [Avahi]: https://en.wikipedia.org/wiki/Avahi_(software)
//! [`MdnsService`]: struct.MdnsService.html
//! [`MdnsBrowser`]: struct.MdnsBrowser.html
//! [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
#[macro_use]
extern crate serde;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate zeroconf_macros;
#[cfg(target_os = "linux")]
extern crate avahi_sys;
#[cfg(target_os = "macos")]
extern crate bonjour_sys;
#[macro_use]
extern crate derive_getters;
#[macro_use]
extern crate log;
extern crate libc;
mod discovery;
mod registration;
pub mod builder;
pub mod ffi;
#[cfg(target_os = "linux")]
pub mod linux;
#[cfg(target_os = "macos")]
pub mod macos;
pub use discovery::*;
pub use registration::*;
/// Type alias for the platform-specific mDNS browser implementation
#[cfg(target_os = "linux")]
pub type MdnsBrowser = linux::browser::AvahiMdnsBrowser;
/// Type alias for the platform-specific mDNS service implementation
#[cfg(target_os = "linux")]
pub type MdnsService = linux::service::AvahiMdnsService;
/// Type alias for the platform-specific mDNS browser implementation
#[cfg(target_os = "macos")]
pub type MdnsBrowser = macos::browser::BonjourMdnsBrowser;
/// Type alias for the platform-specific mDNS service implementation
#[cfg(target_os = "macos")]
pub type MdnsService = macos::service::BonjourMdnsService;

View File

@ -0,0 +1,42 @@
//! Utilities related to Avahi
use super::constants;
use avahi_sys::{avahi_address_snprint, avahi_strerror, AvahiAddress};
use libc::c_char;
use std::ffi::{CStr, CString};
use std::mem;
/// Converts the specified `*const AvahiAddress` to a `String`.
///
/// The new `String` is constructed through allocating a new `CString`, passing it to
/// `avahi_address_snprint` and then converting it to a Rust-type `String`.
pub fn avahi_address_to_string(addr: *const AvahiAddress) -> String {
let addr_str = unsafe {
let str = CString::from_vec_unchecked(vec![0; constants::AVAHI_ADDRESS_STR_MAX]);
avahi_address_snprint(str.as_ptr() as *mut c_char, mem::size_of_val(&str), addr);
str
};
String::from(addr_str.to_str().unwrap())
.trim_matches(char::from(0))
.to_string()
}
/// Returns the `&str` message associated with the specified error code.
pub fn get_error<'a>(code: i32) -> &'a str {
unsafe {
CStr::from_ptr(avahi_strerror(code))
.to_str()
.expect("could not fetch Avahi error string")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_error_returns_valid_error_string() {
assert_eq!(get_error(avahi_sys::AVAHI_ERR_FAILURE), "Operation failed");
}
}

View File

@ -0,0 +1,225 @@
use super::avahi_util;
use super::client::{ManagedAvahiClient, ManagedAvahiClientParams};
use super::constants;
use super::poll::ManagedAvahiSimplePoll;
use super::raw_browser::{ManagedAvahiServiceBrowser, ManagedAvahiServiceBrowserParams};
use super::resolver::{
ManagedAvahiServiceResolver, ManagedAvahiServiceResolverParams, ServiceResolverSet,
};
use crate::builder::BuilderDelegate;
use crate::ffi::{cstr, FromRaw};
use crate::{ServiceDiscoveredCallback, ServiceDiscovery};
use avahi_sys::{
AvahiAddress, AvahiBrowserEvent, AvahiClient, AvahiClientFlags, AvahiClientState, AvahiIfIndex,
AvahiLookupResultFlags, AvahiProtocol, AvahiResolverEvent, AvahiServiceBrowser,
AvahiServiceResolver, AvahiStringList,
};
use libc::{c_char, c_void};
use std::any::Any;
use std::ffi::CString;
use std::sync::Arc;
use std::{fmt, ptr};
#[derive(Debug)]
pub struct AvahiMdnsBrowser {
poll: Option<ManagedAvahiSimplePoll>,
browser: Option<ManagedAvahiServiceBrowser>,
kind: CString,
context: *mut AvahiBrowserContext,
}
impl AvahiMdnsBrowser {
pub fn new(kind: &str) -> Self {
Self {
poll: None,
browser: None,
kind: CString::new(kind.to_string()).unwrap(),
context: Box::into_raw(Box::default()),
}
}
pub fn set_service_discovered_callback(
&mut self,
service_discovered_callback: Box<ServiceDiscoveredCallback>,
) {
unsafe { (*self.context).service_discovered_callback = Some(service_discovered_callback) };
}
pub fn set_context(&mut self, context: Box<dyn Any>) {
unsafe { (*self.context).user_context = Some(Arc::from(context)) };
}
pub fn start(&mut self) -> Result<(), String> {
debug!("Browsing services: {:?}", self);
self.poll = Some(ManagedAvahiSimplePoll::new()?);
let client = ManagedAvahiClient::new(
ManagedAvahiClientParams::builder()
.poll(self.poll.as_ref().unwrap())
.flags(AvahiClientFlags(0))
.callback(Some(client_callback))
.userdata(ptr::null_mut())
.build()?,
)?;
unsafe {
(*self.context).client = Some(client);
self.browser = Some(ManagedAvahiServiceBrowser::new(
ManagedAvahiServiceBrowserParams::builder()
.client(&(*self.context).client.as_ref().unwrap())
.interface(constants::AVAHI_IF_UNSPEC)
.protocol(constants::AVAHI_PROTO_UNSPEC)
.kind(self.kind.as_ptr())
.domain(ptr::null_mut())
.flags(0)
.callback(Some(browse_callback))
.userdata(self.context as *mut c_void)
.build()?,
)?);
}
self.poll.as_ref().unwrap().start_loop()
}
}