mdns-3.0.0/.cargo_vcs_info.json0000644000000001121400477157600120400ustar { "git": { "sha1": "cad16abcd073da964f3e2c00961a0e4efd26cf3f" } } mdns-3.0.0/.gitignore010064400017500001750000000000221374652555200126340ustar 00000000000000target Cargo.lock mdns-3.0.0/.travis.yml010064400017500001750000000000661374652555200127650ustar 00000000000000language: rust rust: - nightly - beta - stable mdns-3.0.0/Cargo.lock0000644000000464531400477157600100350ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "async-attributes" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote", "syn", ] [[package]] name = "async-channel" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" dependencies = [ "concurrent-queue", "event-listener", "futures-core", ] [[package]] name = "async-executor" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146" dependencies = [ "async-task", "concurrent-queue", "fastrand", "futures-lite", "once_cell", "vec-arena", ] [[package]] name = "async-global-executor" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" dependencies = [ "async-channel", "async-executor", "async-io", "async-mutex", "blocking", "futures-lite", "num_cpus", "once_cell", ] [[package]] name = "async-io" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd" dependencies = [ "concurrent-queue", "fastrand", "futures-lite", "libc", "log", "nb-connect", "once_cell", "parking", "polling", "vec-arena", "waker-fn", "winapi", ] [[package]] name = "async-lock" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1996609732bde4a9988bc42125f55f2af5f3c36370e27c778d5191a4a1b63bfb" dependencies = [ "event-listener", ] [[package]] name = "async-mutex" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" dependencies = [ "event-listener", ] [[package]] name = "async-process" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8cea09c1fb10a317d1b5af8024eeba256d6554763e85ecd90ff8df31c7bbda" dependencies = [ "async-io", "blocking", "cfg-if 0.1.10", "event-listener", "futures-lite", "once_cell", "signal-hook", "winapi", ] [[package]] name = "async-std" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" dependencies = [ "async-attributes", "async-channel", "async-global-executor", "async-io", "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", "futures-lite", "gloo-timers", "kv-log-macro", "log", "memchr", "num_cpus", "once_cell", "pin-project-lite", "pin-utils", "slab", "wasm-bindgen-futures", ] [[package]] name = "async-stream" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" dependencies = [ "async-stream-impl", "futures-core", ] [[package]] name = "async-stream-impl" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "async-task" version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "atomic-waker" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "blocking" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" dependencies = [ "async-channel", "async-task", "atomic-waker", "fastrand", "futures-lite", "once_cell", ] [[package]] name = "bumpalo" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f07aa6688c702439a1be0307b6a94dffe1168569e45b9500c1372bc580740d59" [[package]] name = "byteorder" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "cache-padded" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" [[package]] name = "cc" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "concurrent-queue" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" dependencies = [ "cache-padded", ] [[package]] name = "crossbeam-utils" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ "autocfg", "cfg-if 1.0.0", "lazy_static", ] [[package]] name = "ctor" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10bcb9d7dcbf7002aaffbb53eac22906b64cdcc127971dcc387d8eb7c95d5560" dependencies = [ "quote", "syn", ] [[package]] name = "dns-parser" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" dependencies = [ "byteorder", "quick-error", ] [[package]] name = "err-derive" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4" dependencies = [ "proc-macro-error", "proc-macro2", "quote", "rustversion", "syn", "synstructure", ] [[package]] name = "event-listener" version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] name = "fastrand" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" dependencies = [ "instant", ] [[package]] name = "futures-channel" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" dependencies = [ "futures-core", ] [[package]] name = "futures-core" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" [[package]] name = "futures-io" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" [[package]] name = "futures-lite" version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb" dependencies = [ "fastrand", "futures-core", "futures-io", "memchr", "parking", "pin-project-lite", "waker-fn", ] [[package]] name = "futures-macro" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" dependencies = [ "proc-macro-hack", "proc-macro2", "quote", "syn", ] [[package]] name = "futures-task" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" dependencies = [ "once_cell", ] [[package]] name = "futures-util" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", "slab", ] [[package]] name = "gloo-timers" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "hermit-abi" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] [[package]] name = "instant" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "js-sys" version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65" dependencies = [ "wasm-bindgen", ] [[package]] name = "kv-log-macro" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ "log", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ "cfg-if 1.0.0", "value-bag", ] [[package]] name = "mdns" version = "3.0.0" dependencies = [ "async-std", "async-stream", "dns-parser", "err-derive", "futures-core", "futures-util", "log", "net2", ] [[package]] name = "memchr" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "nb-connect" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" dependencies = [ "libc", "winapi", ] [[package]] name = "net2" version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", "libc", "winapi", ] [[package]] name = "num_cpus" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "once_cell" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "pin-project-lite" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "polling" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" dependencies = [ "cfg-if 0.1.10", "libc", "log", "wepoll-sys", "winapi", ] [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", "syn", "version_check", ] [[package]] name = "proc-macro-error-attr" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", "version_check", ] [[package]] name = "proc-macro-hack" version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" 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.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" [[package]] name = "signal-hook" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" dependencies = [ "libc", "signal-hook-registry", ] [[package]] name = "signal-hook-registry" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" dependencies = [ "libc", ] [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "syn" version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "synstructure" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2", "quote", "syn", "unicode-xid", ] [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "value-bag" version = "1.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b676010e055c99033117c2343b33a40a30b91fecd6c49055ac9cd2d6c305ab1" dependencies = [ "ctor", ] [[package]] name = "vec-arena" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" [[package]] name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "waker-fn" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "wasm-bindgen" version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94" dependencies = [ "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64" [[package]] name = "web-sys" version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "wepoll-sys" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" dependencies = [ "cc", ] [[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-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" mdns-3.0.0/Cargo.toml0000644000000024541400477157600100510ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "mdns" version = "3.0.0" authors = ["Dylan McKay "] description = "A multicast DNS client library.\n\nSupports discovery of any mDNS device on a LAN.\n" documentation = "https://docs.rs/mdns" keywords = ["mdns", "dns", "multicast", "chromecast", "discovery"] categories = ["network-programming"] license = "MIT" repository = "https://github.com/dylanmckay/mdns" [dependencies.async-std] version = "1.6.2" features = ["unstable", "attributes"] [dependencies.async-stream] version = "0.2.0" [dependencies.dns-parser] version = "0.8.0" [dependencies.err-derive] version = "0.2.1" [dependencies.futures-core] version = "0.3.1" [dependencies.futures-util] version = "0.3.1" [dependencies.log] version = "0.4" [dependencies.net2] version = "0.2" mdns-3.0.0/Cargo.toml.orig010064400017500001750000000012041400477151500135240ustar 00000000000000[package] name = "mdns" version = "3.0.0" authors = ["Dylan McKay "] edition = "2018" description = """ A multicast DNS client library. Supports discovery of any mDNS device on a LAN. """ license = "MIT" documentation = "https://docs.rs/mdns" repository = "https://github.com/dylanmckay/mdns" categories = ["network-programming"] keywords = ["mdns", "dns", "multicast", "chromecast", "discovery"] [dependencies] dns-parser = "0.8.0" net2 = "0.2" err-derive = "0.2.1" futures-core = "0.3.1" futures-util = "0.3.1" log = "0.4" async-stream = "0.2.0" async-std = { version = "1.6.2", features = ["unstable", "attributes"] } mdns-3.0.0/LICENSE010064400017500001750000000020651374652555200116620ustar 00000000000000The MIT License (MIT) Copyright (c) 2016 Dylan McKay Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mdns-3.0.0/README.md010064400017500001750000000031011400477137500121160ustar 00000000000000# mdns [![Build Status](https://travis-ci.org/dylanmckay/mdns.svg?branch=master)](https://travis-ci.org/dylanmckay/mdns) [![crates.io](https://img.shields.io/crates/v/mdns.svg)](https://crates.io/crates/mdns) [![MIT license](https://img.shields.io/github/license/mashape/apistatus.svg)]() [Documentation](https://docs.rs/mdns) An multicast DNS client in Rust. Error logging is handled with the `log` library. [Wikipedia](https://en.wikipedia.org/wiki/Multicast_DNS) ## Example Find IP addresses for all Chromecasts on the local network. ```rust use futures_util::{pin_mut, stream::StreamExt}; use mdns::{Error, Record, RecordKind}; use std::{net::IpAddr, time::Duration}; const SERVICE_NAME: &'static str = "_googlecast._tcp.local"; #[async_std::main] async fn main() -> Result<(), Error> { // Iterate through responses from each Cast device, asking for new devices every 15s let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen(); pin_mut!(stream); while let Some(Ok(response)) = stream.next().await { let addr = response.records() .filter_map(self::to_ip_addr) .next(); if let Some(addr) = addr { println!("found cast device at {}", addr); } else { println!("cast device does not advertise address"); } } Ok(()) } fn to_ip_addr(record: &Record) -> Option { match record.kind { RecordKind::A(addr) => Some(addr.into()), RecordKind::AAAA(addr) => Some(addr.into()), _ => None, } } ``` mdns-3.0.0/examples/chromecast_discovery.rs010064400017500001750000000012671400477113300172450ustar 00000000000000use futures_util::{pin_mut, stream::StreamExt}; use mdns::Error; use std::time::Duration; const SERVICE_NAME: &'static str = "_googlecast._tcp.local"; #[async_std::main] async fn main() -> Result<(), Error> { let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen(); pin_mut!(stream); while let Some(Ok(response)) = stream.next().await { let addr = response.socket_address(); let host = response.hostname(); if let (Some(host), Some(addr)) = (host, addr) { println!("found cast device {} at {}", host, addr); } else { println!("cast device does not advertise address"); } } Ok(()) } mdns-3.0.0/examples/http_discovery.rs010064400017500001750000000011431400477116100160660ustar 00000000000000use futures_util::{pin_mut, stream::StreamExt}; use mdns::Error; use std::time::Duration; const SERVICE_NAME: &'static str = "_http._tcp.local"; #[async_std::main] async fn main() -> Result<(), Error> { let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen(); pin_mut!(stream); while let Some(Ok(response)) = stream.next().await { let addr = response.ip_addr(); if let Some(addr) = addr { println!("found cast device at {}", addr); } else { println!("cast device does not advertise address"); } } Ok(()) } mdns-3.0.0/examples/resolve_hosts.rs010064400017500001750000000010441400477121100157130ustar 00000000000000use mdns::Error; use std::time::Duration; const SERVICE_NAME: &'static str = "_http._tcp.local"; const HOSTS: [&'static str; 2] = ["server1._http._tcp.local", "server2._http._tcp.local"]; #[async_std::main] async fn main() -> Result<(), Error> { let responses = mdns::resolve::multiple(SERVICE_NAME, &HOSTS, Duration::from_secs(15)).await?; for response in responses { if let (Some(host), Some(ip)) = (response.hostname(), response.ip_addr()) { println!("found host {} at {}", host, ip) } } Ok(()) } mdns-3.0.0/src/discover.rs010064400017500001750000000076731400477141500136270ustar 00000000000000//! Utilities for discovering devices on the LAN. //! //! Examples //! //! ```rust,no_run //! use futures_util::{pin_mut, stream::StreamExt}; //! use mdns::{Error, Record, RecordKind}; //! use std::time::Duration; //! //! const SERVICE_NAME: &'static str = "_googlecast._tcp.local"; //! //! #[async_std::main] //! async fn main() -> Result<(), Error> { //! let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen(); //! pin_mut!(stream); //! //! while let Some(Ok(response)) = stream.next().await { //! println!("{:?}", response); //! } //! //! Ok(()) //! } //! ``` use crate::{mDNSListener, Error, Response}; use std::time::Duration; use crate::mdns::{mDNSSender, mdns_interface}; use futures_core::Stream; use futures_util::{future::ready, stream::select, StreamExt}; use std::net::Ipv4Addr; /// A multicast DNS discovery request. /// /// This represents a single lookup of a single service name. /// /// This object can be iterated over to yield the received mDNS responses. pub struct Discovery { service_name: String, mdns_sender: mDNSSender, mdns_listener: mDNSListener, /// Whether we should ignore empty responses. ignore_empty: bool, /// The interval we should send mDNS queries. send_request_interval: Duration, } /// Gets an iterator over all responses for a given service on all interfaces. pub fn all(service_name: S, mdns_query_interval: Duration) -> Result where S: AsRef, { interface(service_name, mdns_query_interval, Ipv4Addr::new(0, 0, 0, 0)) } /// Gets an iterator over all responses for a given service on a given interface. pub fn interface( service_name: S, mdns_query_interval: Duration, interface_addr: Ipv4Addr, ) -> Result where S: AsRef, { let service_name = service_name.as_ref().to_string(); let (mdns_listener, mdns_sender) = mdns_interface(service_name.clone(), interface_addr)?; Ok(Discovery { service_name, mdns_sender, mdns_listener, ignore_empty: true, send_request_interval: mdns_query_interval, }) } impl Discovery { /// Sets whether or not we should ignore empty responses. /// /// Defaults to `true`. pub fn ignore_empty(mut self, ignore: bool) -> Self { self.ignore_empty = ignore; self } pub fn listen(self) -> impl Stream> { let ignore_empty = self.ignore_empty; let service_name = self.service_name; let response_stream = self.mdns_listener.listen().map(StreamResult::Response); let sender = self.mdns_sender.clone(); let interval_stream = async_std::stream::interval(self.send_request_interval) // I don't like the double clone, I can't find a prettier way to do this .map(move |_| { let mut sender = sender.clone(); async_std::task::spawn(async move { let _ = sender.send_request().await; }); StreamResult::Interval }); let stream = select(response_stream, interval_stream); stream .filter_map(|stream_result| { async { match stream_result { StreamResult::Interval => None, StreamResult::Response(res) => Some(res), } } }) .filter(move |res| { ready(match res { Ok(response) => { (!response.is_empty() || !ignore_empty) && response .answers .iter() .any(|record| record.name == service_name) } Err(_) => true, }) }) } } enum StreamResult { Interval, Response(Result), } mdns-3.0.0/src/errors.rs010064400017500001750000000004641400477073400133170ustar 00000000000000use err_derive::Error; #[derive(Debug, Error)] pub enum Error { #[error(display = "_0")] Io(#[error(source)] std::io::Error), #[error(display = "_0")] Dns(#[error(source)] dns_parser::Error), #[error(display = "_0")] TimeoutError(#[error(source)] async_std::future::TimeoutError), } mdns-3.0.0/src/io.rs010064400017500001750000000017511400476750400124130ustar 00000000000000use crate::{Error, mDNS}; use std::time::Duration; use mio; pub struct Io { pub poll: mio::Poll, pub events: mio::Events, token_accumulator: usize, } impl Io { pub fn new() -> Result { let poll = mio::Poll::new()?; let events = mio::Events::with_capacity(1024); Ok(Io { poll, events, token_accumulator: 0, }) } pub fn poll(&mut self, mdns: &mut mDNS, timeout: Option) -> Result<(), Error> { self.poll.poll(&mut self.events, timeout)?; for event in self.events.iter() { if event.readiness().is_readable() { mdns.recv(event.token())? }; if event.readiness().is_writable() { mdns.send(event.token())? }; } Ok(()) } pub fn create_token(&mut self) -> mio::Token { let token = mio::Token(self.token_accumulator); self.token_accumulator += 1; token } } mdns-3.0.0/src/lib.rs010064400017500001750000000044421400477136300125500ustar 00000000000000//! [Multicast DNS](https://en.wikipedia.org/wiki/Multicast_DNS) library with built-in networking. //! //! This crate can be used to discover mDNS devices that are listening //! on a network. //! //! # Basic usage //! //! This example finds all [Chromecast](https://en.wikipedia.org/wiki/Chromecast) devices on the //! same LAN as the executing computer. //! //! Once the devices are discovered, they respond with standard DNS records, with a few minor //! low-level protocol differences. //! //! The only Chromecast-specific piece of code here is the `SERVICE_NAME`. In order to discover //! other types of devices, simply change the service name to the one your device uses. //! //! This example obtains the IP addresses of the cast devices by looking up `A`/`AAAA` records. //! //! ```rust,no_run //! use futures_util::{pin_mut, stream::StreamExt}; //! use mdns::{Error, Record, RecordKind}; //! use std::{net::IpAddr, time::Duration}; //! //! /// The hostname of the devices we are searching for. //! /// Every Chromecast will respond to the service name in this example. //! const SERVICE_NAME: &'static str = "_googlecast._tcp.local"; //! //! #[async_std::main] //! async fn main() -> Result<(), Error> { //! // Iterate through responses from each Cast device, asking for new devices every 15s //! let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen(); //! pin_mut!(stream); //! //! while let Some(Ok(response)) = stream.next().await { //! let addr = response.records() //! .filter_map(self::to_ip_addr) //! .next(); //! //! if let Some(addr) = addr { //! println!("found cast device at {}", addr); //! } else { //! println!("cast device does not advertise address"); //! } //! } //! //! Ok(()) //! } //! //! fn to_ip_addr(record: &Record) -> Option { //! match record.kind { //! RecordKind::A(addr) => Some(addr.into()), //! RecordKind::AAAA(addr) => Some(addr.into()), //! _ => None, //! } //! } //! ``` #![recursion_limit = "1024"] pub use self::errors::Error; pub use self::response::{Record, RecordKind, Response}; pub mod discover; pub mod resolve; mod errors; mod mdns; mod response; pub use self::mdns::mDNSListener; mdns-3.0.0/src/mdns.rs010064400017500001750000000055711400477073400127500ustar 00000000000000use crate::{Error, Response}; use std::{io, net::Ipv4Addr}; use async_stream::try_stream; use futures_core::Stream; use std::sync::Arc; use async_std::net::UdpSocket; #[cfg(not(target_os = "windows"))] use net2::unix::UnixUdpBuilderExt; use std::net::SocketAddr; /// The IP address for the mDNS multicast socket. const MULTICAST_ADDR: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251); const MULTICAST_PORT: u16 = 5353; pub fn mdns_interface( service_name: String, interface_addr: Ipv4Addr, ) -> Result<(mDNSListener, mDNSSender), Error> { let socket = create_socket()?; socket.set_multicast_loop_v4(false)?; socket.join_multicast_v4(&MULTICAST_ADDR, &interface_addr)?; let socket = Arc::new(UdpSocket::from(socket)); let recv_buffer = vec![0; 4096]; Ok(( mDNSListener { recv: socket.clone(), recv_buffer }, mDNSSender { service_name, send: socket }, )) } const ADDR_ANY: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0); #[cfg(not(target_os = "windows"))] fn create_socket() -> io::Result { net2::UdpBuilder::new_v4()? .reuse_address(true)? .reuse_port(true)? .bind((ADDR_ANY, MULTICAST_PORT)) } #[cfg(target_os = "windows")] fn create_socket() -> io::Result { net2::UdpBuilder::new_v4()? .reuse_address(true)? .bind((ADDR_ANY, MULTICAST_PORT)) } /// An mDNS sender on a specific interface. #[derive(Debug, Clone)] #[allow(non_camel_case_types)] pub struct mDNSSender<> { service_name: String, send: Arc, } impl mDNSSender { /// Send multicasted DNS queries. pub async fn send_request(&mut self) -> Result<(), Error> { let mut builder = dns_parser::Builder::new_query(0, false); let prefer_unicast = false; builder.add_question( &self.service_name, prefer_unicast, dns_parser::QueryType::PTR, dns_parser::QueryClass::IN, ); let packet_data = builder.build().unwrap(); let addr = SocketAddr::new(MULTICAST_ADDR.into(), MULTICAST_PORT); self.send.send_to(&packet_data, addr).await?; Ok(()) } } /// An mDNS listener on a specific interface. #[derive(Debug, Clone)] #[allow(non_camel_case_types)] pub struct mDNSListener { recv: Arc, recv_buffer: Vec, } impl mDNSListener { pub fn listen(mut self) -> impl Stream> { try_stream! { loop { let (count, _) = self.recv.recv_from(&mut self.recv_buffer).await?; if count > 0 { match dns_parser::Packet::parse(&self.recv_buffer[..count]) { Ok(raw_packet) => yield Response::from_packet(&raw_packet), Err(e) => log::warn!("{}, {:?}", e, &self.recv_buffer[..count]), } } } } } } mdns-3.0.0/src/resolve.rs010064400017500001750000000045401400477140500134550ustar 00000000000000//! Utilities for resolving a devices on the LAN. //! //! Examples //! //! ```rust,no_run //! use mdns::Error; //! use std::time::Duration; //! //! const SERVICE_NAME: &'static str = "_googlecast._tcp.local"; //! const HOST: &'static str = "mycast._googlecast._tcp.local"; //! //! #[async_std::main] //! async fn main() -> Result<(), Error> { //! if let Some(response) = mdns::resolve::one(SERVICE_NAME, HOST, Duration::from_secs(15)).await? { //! println!("{:?}", response); //! } //! //! Ok(()) //! } //! ``` use crate::{Error, Response}; use futures_util::{StreamExt, pin_mut, TryFutureExt}; use std::time::Duration; /// Resolve a single device by hostname pub async fn one( service_name: &str, host_name: S, timeout: Duration, ) -> Result, Error> where S: AsRef, { // by setting the query interval higher than the timeout we ensure we only make one query let stream = crate::discover::all(service_name, timeout * 2)?.listen(); pin_mut!(stream); let process = async { while let Some(Ok(response)) = stream.next().await { match response.hostname() { Some(found_host) if found_host == host_name.as_ref() => return Some(response), _ => {} } } None }; async_std::future::timeout(timeout, process).map_err(|e| e.into()).await } /// Resolve multiple devices by hostname pub async fn multiple( service_name: &str, host_names: &[S], timeout: Duration, ) -> Result, Error> where S: AsRef, { // by setting the query interval higher than the timeout we ensure we only make one query let stream = crate::discover::all(service_name, timeout * 2)?.listen(); pin_mut!(stream); let mut found = Vec::new(); let process = async { while let Some(Ok(response)) = stream.next().await { match response.hostname() { Some(found_host) if host_names.iter().any(|s| s.as_ref() == found_host) => { found.push(response); if found.len() == host_names.len() { return; } } _ => {} } } }; match async_std::future::timeout(timeout, process).await { Ok(()) => Ok(found), Err(e) => Err(e.into()) } } mdns-3.0.0/src/response.rs010064400017500001750000000111661400476750400136430ustar 00000000000000use std::net; use std::net::{IpAddr, SocketAddr}; /// A DNS response. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Response { pub answers: Vec, pub nameservers: Vec, pub additional: Vec, } /// Any type of DNS record. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Record { pub name: String, pub class: dns_parser::Class, pub ttl: u32, pub kind: RecordKind, } /// A specific DNS record variant. #[derive(Clone, Debug, PartialEq, Eq)] pub enum RecordKind { A(net::Ipv4Addr), AAAA(net::Ipv6Addr), CNAME(String), MX { preference: u16, exchange: String, }, NS(String), SRV { priority: u16, weight: u16, port: u16, target: String, }, TXT(Vec), PTR(String), /// A record kind that hasn't been implemented by this library yet. Unimplemented(Vec), } impl Response { pub fn from_packet(packet: &dns_parser::Packet) -> Self { Response { answers: packet .answers .iter() .map(Record::from_resource_record) .collect(), nameservers: packet .nameservers .iter() .map(Record::from_resource_record) .collect(), additional: packet .additional .iter() .map(Record::from_resource_record) .collect(), } } pub fn records(&self) -> impl Iterator { self.answers .iter() .chain(self.nameservers.iter()) .chain(self.additional.iter()) } pub fn is_empty(&self) -> bool { self.answers.is_empty() && self.nameservers.is_empty() && self.additional.is_empty() } pub fn ip_addr(&self) -> Option { self.records().find_map(|record| match record.kind { RecordKind::A(addr) => Some(addr.into()), RecordKind::AAAA(addr) => Some(addr.into()), _ => None, }) } pub fn hostname(&self) -> Option<&str> { self.records().find_map(|record| match record.kind { RecordKind::PTR(ref host) => Some(host.as_str()), _ => None, }) } pub fn port(&self) -> Option { self.records().find_map(|record| match record.kind { RecordKind::SRV { port, .. } => Some(port), _ => None, }) } pub fn socket_address(&self) -> Option { Some((self.ip_addr()?, self.port()?).into()) } pub fn txt_records(&self) -> impl Iterator { self.records() .filter_map(|record| match record.kind { RecordKind::TXT(ref txt) => Some(txt), _ => None, }) .flat_map(|txt| txt.iter()) .map(|txt| txt.as_str()) } } impl Record { fn from_resource_record(rr: &dns_parser::ResourceRecord) -> Self { Record { name: rr.name.to_string(), class: rr.cls, ttl: rr.ttl, kind: RecordKind::from_rr_data(&rr.data), } } } impl RecordKind { fn from_rr_data(data: &dns_parser::RData) -> Self { use dns_parser::RData; match *data { RData::A(dns_parser::rdata::a::Record(addr)) => RecordKind::A(addr), RData::AAAA(dns_parser::rdata::aaaa::Record(addr)) => RecordKind::AAAA(addr), RData::CNAME(ref name) => RecordKind::CNAME(name.to_string()), RData::MX(dns_parser::rdata::mx::Record { preference, ref exchange, }) => RecordKind::MX { preference, exchange: exchange.to_string(), }, RData::NS(ref name) => RecordKind::NS(name.to_string()), RData::PTR(ref name) => RecordKind::PTR(name.to_string()), RData::SRV(dns_parser::rdata::srv::Record { priority, weight, port, ref target, }) => RecordKind::SRV { priority, weight, port, target: target.to_string(), }, RData::TXT(ref txt) => RecordKind::TXT( txt.iter() .map(|bytes| String::from_utf8_lossy(bytes).into_owned()) .collect(), ), RData::SOA(..) => { RecordKind::Unimplemented("SOA record handling is not implemented".into()) } RData::Unknown(data) => RecordKind::Unimplemented(data.to_owned()), } } }