Move from magiclip project
Signed-off-by: Walker Crouse <walker.crouse@coop.co.uk>
This commit is contained in:
parent
5a1b5a3505
commit
55cbcfe154
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
**/target
|
506
Cargo.lock
generated
Normal file
506
Cargo.lock
generated
Normal 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
5
Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"zeroconf",
|
||||
"zeroconf-macros",
|
||||
]
|
89
README.md
Normal file
89
README.md
Normal 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
520
examples/Cargo.lock
generated
Normal 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
5
examples/Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"browser",
|
||||
"service",
|
||||
]
|
8
examples/browser/Cargo.toml
Normal file
8
examples/browser/Cargo.toml
Normal 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" }
|
18
examples/browser/src/main.rs
Normal file
18
examples/browser/src/main.rs
Normal 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);
|
||||
|
||||
// ...
|
||||
}
|
8
examples/service/Cargo.toml
Normal file
8
examples/service/Cargo.toml
Normal 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" }
|
36
examples/service/src/main.rs
Normal file
36
examples/service/src/main.rs
Normal 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);
|
||||
|
||||
// ...
|
||||
}
|
12
zeroconf-macros/Cargo.toml
Normal file
12
zeroconf-macros/Cargo.toml
Normal 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"
|
70
zeroconf-macros/src/lib.rs
Normal file
70
zeroconf-macros/src/lib.rs
Normal 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
19
zeroconf/Cargo.toml
Normal 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
9
zeroconf/src/builder.rs
Normal 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
25
zeroconf/src/discovery.rs
Normal 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
62
zeroconf/src/ffi.rs
Normal 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
128
zeroconf/src/lib.rs
Normal 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;
|
42
zeroconf/src/linux/avahi_util.rs
Normal file
42
zeroconf/src/linux/avahi_util.rs
Normal 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");
|
||||
}
|
||||
}
|
225
zeroconf/src/linux/browser.rs
Normal file
225
zeroconf/src/linux/browser.rs
Normal 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()
|
||||
}
|
||||
}
|
||||