From 3c83311b16cbee3e379f68f04fae661bc8abcc66 Mon Sep 17 00:00:00 2001 From: Alexey Aristov Date: Mon, 6 Jan 2020 00:41:17 +0100 Subject: [PATCH 1/6] initial async support --- Cargo.lock | 312 ++++++++++++++++++++++++++++++++- Cargo.toml | 5 + src/dtls_acceptor.rs | 6 +- src/dtls_connector.rs | 57 ++++-- src/dtls_stream.rs | 144 ++++++++------- src/dtls_stream_async.rs | 61 +++++++ src/lib.rs | 10 +- src/midhandshake_dtls_steam.rs | 8 +- src/udp_channel.rs | 10 +- src/udp_channel_async.rs | 35 ++++ 10 files changed, 553 insertions(+), 95 deletions(-) create mode 100644 src/dtls_stream_async.rs create mode 100644 src/udp_channel_async.rs diff --git a/Cargo.lock b/Cargo.lock index ccc230e..c1a70e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,11 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bytes" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cc" version = "1.0.30" @@ -26,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -42,6 +47,102 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-executor" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-macro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-sink" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iovec" version = "0.1.2" @@ -51,6 +152,15 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "1.3.0" @@ -66,7 +176,51 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mio" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -75,7 +229,7 @@ version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", @@ -108,11 +262,52 @@ dependencies = [ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pin-project-lite" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro-hack" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-nested" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -134,16 +329,59 @@ name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-openssl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "udp-dtls" version = "0.1.0" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-openssl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -154,25 +392,91 @@ name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-src 111.1.1+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)" = "26de02d64280c73cdc67270966dd6eafe59d8e764faae4b8773f82a882a3f1cc" "checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum tokio 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1bef565a52394086ecac0a6fa3b8ace4cb3a138ee1d96bd2b93283b56824e3" +"checksum tokio-openssl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c4b08c5f4208e699ede3df2520aca2e82401b2de33f45e96696a074480be594" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/Cargo.toml b/Cargo.toml index 16538df..fbe9c4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,11 @@ openssl = "0.10.19" openssl-probe = "0.1.2" log = "0.4.6" bytes = "0.4.11" +futures = {version = "0.3", optional = false} +tokio = {version = "0.2", features = ["default", "udp"], optional = false} +tokio-openssl = {version="0.4", optional=false} [features] vendored = ["openssl/vendored"] +#async = ["futures", "tokio", "tokio-openssl"] + diff --git a/src/dtls_acceptor.rs b/src/dtls_acceptor.rs index 904429f..686d57a 100644 --- a/src/dtls_acceptor.rs +++ b/src/dtls_acceptor.rs @@ -1,5 +1,5 @@ use crate::openssl::try_set_supported_protocols; -use crate::{DtlsAcceptorBuilder, DtlsStream, HandshakeError, CertificateIdentity, Protocol, Result}; +use crate::{DtlsAcceptorBuilder, SyncDtlsStream, HandshakeError, CertificateIdentity, Protocol, Result}; use openssl::ssl::{SslAcceptor, SslMethod}; use std::{fmt, io, result}; @@ -75,12 +75,12 @@ impl DtlsAcceptor { pub fn accept( &self, stream: S, - ) -> result::Result, HandshakeError> + ) -> result::Result, HandshakeError> where S: io::Read + io::Write, { let stream = self.0.accept(stream)?; - Ok(DtlsStream::from(stream)) + Ok(SyncDtlsStream::from(stream)) } } diff --git a/src/dtls_connector.rs b/src/dtls_connector.rs index 7ef71c6..178ab86 100644 --- a/src/dtls_connector.rs +++ b/src/dtls_connector.rs @@ -1,11 +1,13 @@ use crate::{ openssl::{init_trust, try_set_supported_protocols}, - DtlsConnectorBuilder, DtlsStream, Error, HandshakeError, Protocol, ConnectorIdentity + DtlsConnectorBuilder, SyncDtlsStream, Error, AsyncDtlsStream, Protocol, ConnectorIdentity }; use log::debug; -use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode}; +use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode, ConnectConfiguration, HandshakeError}; use openssl::error::ErrorStack; use std::{fmt, io, io::Write}; +use tokio_openssl; +use tokio::io::{AsyncRead, AsyncWrite}; /// Connector to an UDP endpoint secured with DTLS. #[derive(Clone)] @@ -21,7 +23,7 @@ impl DtlsConnector { /// /// The `DtlsConnector` will use the settings from the given builder. /// - /// The following propperties will be applied from the builder: + /// The following properties will be applied from the builder: /// - Sets minimal/maximal protocol version /// - Sets srtp profile by enabling the DTLS extension 'use_srtp' /// - Sets the certificate and private key @@ -109,6 +111,20 @@ impl DtlsConnector { } } + fn configure(&self) -> Result { + let mut ssl = self + .connector + .configure()? + .use_server_name_indication(self.use_sni) + .verify_hostname(!self.accept_invalid_hostnames); + + if self.accept_invalid_certs { + ssl.set_verify(SslVerifyMode::NONE); + } + + Ok(ssl) + } + /// Initiates a DTLS handshake. /// /// The provided domain will be used for both SNI and certificate hostname @@ -125,22 +141,35 @@ impl DtlsConnector { &self, domain: &str, stream: S, - ) -> Result, HandshakeError> + ) -> Result, HandshakeError> where S: io::Read + io::Write, { - let mut ssl = self - .connector - .configure()? - .use_server_name_indication(self.use_sni) - .verify_hostname(!self.accept_invalid_hostnames); - if self.accept_invalid_certs { - ssl.set_verify(SslVerifyMode::NONE); - } + let conf = self.configure()?; + let stream = conf.connect(domain, stream)?; - let stream = ssl.connect(domain, stream)?; - Ok(DtlsStream::from(stream)) + Ok(SyncDtlsStream::from(stream)) } + + pub async fn async_connect( + &self, + domain: &str, + stream: S, + ) -> Result, AsyncConnectError> + where + S: AsyncRead + AsyncWrite + Unpin + { + let conf = self.configure().map_err(AsyncConnectError::ErrorStack)?; + let stream = tokio_openssl::connect(conf, domain, stream).await.map_err(AsyncConnectError::TokioOpenSsl)?; + + Ok(AsyncDtlsStream::from(stream)) + } +} + +#[derive(Debug)] +pub enum AsyncConnectError { + ErrorStack(ErrorStack), + TokioOpenSsl(tokio_openssl::HandshakeError) } impl AsRef for DtlsConnector { diff --git a/src/dtls_stream.rs b/src/dtls_stream.rs index 2b10a09..5186669 100644 --- a/src/dtls_stream.rs +++ b/src/dtls_stream.rs @@ -1,6 +1,6 @@ use crate::{Certificate, Error, SrtpProfile}; use openssl::ssl; -use openssl::ssl::SslStream; +use openssl::ssl::{SslStream, SslRef}; use std::{fmt, io}; /// A stream managing a DTLS session. @@ -9,81 +9,33 @@ use std::{fmt, io}; /// and both the server and the client are ready for receiving and sending /// data. Bytes read from a `DtlsStream` are decrypted from `S` and bytes written /// to a `DtlsStream` are encrypted when passing through to `S`. -pub struct DtlsStream(ssl::SslStream); +pub struct DtlsStream(pub(crate) C); -impl fmt::Debug for DtlsStream { +pub type SyncDtlsStream = DtlsStream>; + +impl fmt::Debug for DtlsStream> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, fmt) } } -impl DtlsStream { - /// Export keying material - /// - /// # Underlying SSL - /// This corresponds to [`SSL_export_keying_material`]. - /// - /// [`SSL_export_keying_material`]: https://www.openssl.org/docs/manmaster/man3/SSL_export_keying_material.html - pub fn keying_material(&self, len: usize) -> Result, Error> { - let mut buf = vec![0; len]; - self.0 - .ssl() - .export_keying_material(&mut buf, "EXTRACTOR-dtls_srtp", None)?; - Ok(buf) - } - - /// Gets the SRTP profile selected by handshake. - /// - /// # Underlying SSL - /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. - /// - /// This corresponds to [`SSL_get_selected_srtp_profile`]. - /// - /// [`SSL_get_selected_srtp_profile`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html - pub fn selected_srtp_profile(&self) -> Result, Error> { - match self.0.ssl().selected_srtp_profile() { - Some(profile) => Ok(profile.name().parse()?).map(Some), - None => Ok(None), - } +impl DtlsStreamExt for SyncDtlsStream { + fn ssl(&self) -> &SslRef { + &self.0.ssl() } /// Returns a shared reference to the underlying stream. - pub fn get_ref(&self) -> &S { + fn get_ref(&self) -> &S { self.0.get_ref() } /// Returns a mutable reference to the inner stream. - pub fn get_mut(&mut self) -> &mut S { + fn get_mut(&mut self) -> &mut S { self.0.get_mut() } +} - /// Returns the number of bytes remaining in the currently processed TLS record. - /// - /// If this is greater than 0, the next call to `read` will not call down to the underlying - /// stream. - /// - /// # Underlying SSL - /// This corresponds to [`SSL_pending`]. - /// - /// [`SSL_pending`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_pending.html - pub fn buffered_read_size(&self) -> Result { - Ok(self.0.ssl().pending()) - } - - /// Returns the peer's certificate, if present. - /// - /// # Underlying SSL - /// This corresponds to [`SSL_get_peer_certificate`]. - /// - /// [`SSL_get_peer_certificate`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_peer_certificate.html - pub fn peer_certificate(&self) -> Result, Error> { - Ok(self - .0 - .ssl() - .peer_certificate() - .map(|c| Certificate::from(c))) - } - +impl SyncDtlsStream { /// Shuts down the session. /// /// The shutdown process consists of two steps. The first step sends a close notify message to @@ -101,6 +53,7 @@ impl DtlsStream { pub fn shutdown(&mut self) -> io::Result<()> { match self.0.shutdown() { Ok(_) => Ok(()), + Err(ref e) if e.code() == ssl::ErrorCode::ZERO_RETURN => Ok(()), Err(e) => Err(e .into_io_error() @@ -109,13 +62,13 @@ impl DtlsStream { } } -impl io::Read for DtlsStream { +impl io::Read for SyncDtlsStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } -impl io::Write for DtlsStream { +impl io::Write for SyncDtlsStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -125,14 +78,77 @@ impl io::Write for DtlsStream { } } -impl AsRef> for DtlsStream { +impl AsRef> for SyncDtlsStream { fn as_ref(&self) -> &SslStream { &self.0 } } -impl From> for DtlsStream { +impl From> for SyncDtlsStream { fn from(stream: SslStream) -> Self { DtlsStream(stream) } } + + +pub trait DtlsStreamExt { + fn ssl(&self) -> &SslRef; + fn get_ref(&self) -> &S; + fn get_mut(&mut self) -> &mut S; + + /// Export keying material + /// + /// # Underlying SSL + /// This corresponds to [`SSL_export_keying_material`]. + /// + /// [`SSL_export_keying_material`]: https://www.openssl.org/docs/manmaster/man3/SSL_export_keying_material.html + fn keying_material(&self, len: usize) -> Result, Error> { + let mut buf = vec![0; len]; + self + .ssl() + .export_keying_material(&mut buf, "EXTRACTOR-dtls_srtp", None)?; + Ok(buf) + } + + /// Gets the SRTP profile selected by handshake. + /// + /// # Underlying SSL + /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. + /// + /// This corresponds to [`SSL_get_selected_srtp_profile`]. + /// + /// [`SSL_get_selected_srtp_profile`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html + fn selected_srtp_profile(&self) -> Result, Error> { + match self.ssl().selected_srtp_profile() { + Some(profile) => Ok(profile.name().parse()?).map(Some), + None => Ok(None), + } + } + + + /// Returns the number of bytes remaining in the currently processed TLS record. + /// + /// If this is greater than 0, the next call to `read` will not call down to the underlying + /// stream. + /// + /// # Underlying SSL + /// This corresponds to [`SSL_pending`]. + /// + /// [`SSL_pending`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_pending.html + fn buffered_read_size(&self) -> Result { + Ok(self.ssl().pending()) + } + + /// Returns the peer's certificate, if present. + /// + /// # Underlying SSL + /// This corresponds to [`SSL_get_peer_certificate`]. + /// + /// [`SSL_get_peer_certificate`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_peer_certificate.html + fn peer_certificate(&self) -> Result, Error> { + Ok(self + .ssl() + .peer_certificate() + .map(|c| Certificate::from(c))) + } +} diff --git a/src/dtls_stream_async.rs b/src/dtls_stream_async.rs new file mode 100644 index 0000000..2070ce5 --- /dev/null +++ b/src/dtls_stream_async.rs @@ -0,0 +1,61 @@ +use std::{pin::Pin, task::{Context, Poll}, io, fmt}; +use openssl::ssl::{SslRef}; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio_openssl::SslStream as AsyncSslStream; + +use crate::{DtlsStream, DtlsStreamExt}; + +pub type AsyncDtlsStream = DtlsStream>; + +impl fmt::Debug for DtlsStream> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, fmt) + } +} + +impl DtlsStreamExt for AsyncDtlsStream { + fn ssl(&self) -> &SslRef { + self.0.ssl() + } + + fn get_ref(&self) -> &S { + self.0.get_ref() + } + + fn get_mut(&mut self) -> &mut S { + self.0.get_mut() + } +} + +impl AsyncRead for AsyncDtlsStream { + fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context, buf: &mut[u8]) -> Poll> { + Pin::new(&mut self.0).poll_read(cx, buf) + } +} + +impl AsyncWrite for AsyncDtlsStream { + fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { + Pin::new(&mut self.0).poll_write(cx, buf) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + Pin::new(&mut self.0).poll_flush(cx) + } + + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + Pin::new(&mut self.0).poll_shutdown(cx) + } +} + +impl AsRef> for AsyncDtlsStream { + fn as_ref(&self) -> &AsyncSslStream { + &self.0 + } +} + +impl From> for AsyncDtlsStream { + fn from(stream: AsyncSslStream) -> Self { + DtlsStream(stream) + } +} + diff --git a/src/lib.rs b/src/lib.rs index 1b625aa..01f1c97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,16 +15,22 @@ mod protocol; mod srtp_profile; mod udp_channel; +mod udp_channel_async; +mod dtls_stream_async; + pub use self::certificate::Certificate; pub use self::certificate_fingerprint::{CertificateFingerprint, SignatureAlgorithm}; pub use self::dtls_acceptor::DtlsAcceptor; pub use self::dtls_acceptor_builder::DtlsAcceptorBuilder; pub use self::dtls_connection_builder::DtlsConnectorBuilder; pub use self::dtls_connector::DtlsConnector; -pub use self::dtls_stream::DtlsStream; +pub use self::dtls_stream::{SyncDtlsStream, DtlsStreamExt, DtlsStream}; pub use self::error::{Error, HandshakeError, Result, SrtpProfileError}; pub use self::identity::{ConnectorIdentity, CertificateIdentity, PskIdentity}; pub use self::midhandshake_dtls_steam::MidHandshakeDtlsStream; pub use self::protocol::Protocol; pub use self::srtp_profile::SrtpProfile; -pub use self::udp_channel::UdpChannel; +pub use self::udp_channel::{UdpChannel, SyncUdpChannel}; + +pub use self::udp_channel_async::{AsyncUdpChannel}; +pub use self::dtls_stream_async::{AsyncDtlsStream}; diff --git a/src/midhandshake_dtls_steam.rs b/src/midhandshake_dtls_steam.rs index 5b5ac67..45efcac 100644 --- a/src/midhandshake_dtls_steam.rs +++ b/src/midhandshake_dtls_steam.rs @@ -1,5 +1,5 @@ -use crate::{DtlsStream, HandshakeError}; -use openssl::ssl::MidHandshakeSslStream; +use crate::{SyncDtlsStream, HandshakeError}; +use openssl::ssl::{MidHandshakeSslStream}; use std::{fmt, io}; /// A DTLS stream which has been interrupted midway through the handshake process. @@ -35,9 +35,9 @@ where /// This corresponds to [`SSL_do_handshake`]. /// /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html - pub fn handshake(self) -> Result, HandshakeError> { + pub fn handshake(self) -> Result, HandshakeError> { match self.0.handshake() { - Ok(s) => Ok(DtlsStream::from(s)), + Ok(s) => Ok(SyncDtlsStream::from(s)), Err(e) => Err(e.into()), } } diff --git a/src/udp_channel.rs b/src/udp_channel.rs index 49e5a6d..192c9cd 100644 --- a/src/udp_channel.rs +++ b/src/udp_channel.rs @@ -4,18 +4,20 @@ use std::result; /// Wrapper to read from and sent data to an remote UDP endpoint. #[derive(Debug)] -pub struct UdpChannel { - pub socket: UdpSocket, +pub struct UdpChannel { + pub socket: S, pub remote_addr: SocketAddr, } -impl Read for UdpChannel { +pub type SyncUdpChannel = UdpChannel; + +impl Read for SyncUdpChannel { fn read(&mut self, buf: &mut [u8]) -> Result { self.socket.recv(buf) } } -impl Write for UdpChannel { +impl Write for SyncUdpChannel { fn write(&mut self, buf: &[u8]) -> Result { self.socket.send_to(buf, self.remote_addr) } diff --git a/src/udp_channel_async.rs b/src/udp_channel_async.rs new file mode 100644 index 0000000..0c44083 --- /dev/null +++ b/src/udp_channel_async.rs @@ -0,0 +1,35 @@ +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::io::Result; +use tokio::net::UdpSocket as AsyncUdpSocket; +use tokio::io::{AsyncRead, AsyncWrite}; +use futures::future::FutureExt; + +use crate::UdpChannel; + +pub type AsyncUdpChannel = UdpChannel; + +impl Unpin for AsyncUdpChannel {} + +impl AsyncRead for AsyncUdpChannel { + fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context, buf: &mut[u8]) -> Poll> { + let mut future = Box::pin(self.socket.recv(buf)); + future.poll_unpin(cx) + } +} + +impl AsyncWrite for AsyncUdpChannel { + fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll>{ + let remote_addr = self.remote_addr; + let mut future = Box::pin(self.socket.send_to(buf, remote_addr)); + future.poll_unpin(cx) + } + + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } +} From ebb9d4ff80ab4028fac819cd46afe8c4b5fee27d Mon Sep 17 00:00:00 2001 From: Alexey Aristov Date: Mon, 6 Jan 2020 00:53:20 +0100 Subject: [PATCH 2/6] hide async support under 'async' feature flag --- Cargo.toml | 8 ++++---- src/dtls_connector.rs | 9 ++++++++- src/lib.rs | 4 ++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fbe9c4c..7efc5e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,11 +16,11 @@ openssl = "0.10.19" openssl-probe = "0.1.2" log = "0.4.6" bytes = "0.4.11" -futures = {version = "0.3", optional = false} -tokio = {version = "0.2", features = ["default", "udp"], optional = false} -tokio-openssl = {version="0.4", optional=false} +futures = {version = "0.3", optional = true} +tokio = {version = "0.2", features = ["default", "udp"], optional = true} +tokio-openssl = {version="0.4", optional = true} [features] vendored = ["openssl/vendored"] -#async = ["futures", "tokio", "tokio-openssl"] +async = ["futures", "tokio", "tokio-openssl"] diff --git a/src/dtls_connector.rs b/src/dtls_connector.rs index 178ab86..dc00f5d 100644 --- a/src/dtls_connector.rs +++ b/src/dtls_connector.rs @@ -1,12 +1,17 @@ use crate::{ openssl::{init_trust, try_set_supported_protocols}, - DtlsConnectorBuilder, SyncDtlsStream, Error, AsyncDtlsStream, Protocol, ConnectorIdentity + DtlsConnectorBuilder, SyncDtlsStream, Error, Protocol, ConnectorIdentity }; use log::debug; use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode, ConnectConfiguration, HandshakeError}; use openssl::error::ErrorStack; use std::{fmt, io, io::Write}; + +#[cfg(feature="async")] +use crate::AsyncDtlsStream; +#[cfg(feature="async")] use tokio_openssl; +#[cfg(feature="async")] use tokio::io::{AsyncRead, AsyncWrite}; /// Connector to an UDP endpoint secured with DTLS. @@ -151,6 +156,7 @@ impl DtlsConnector { Ok(SyncDtlsStream::from(stream)) } + #[cfg(feature="async")] pub async fn async_connect( &self, domain: &str, @@ -166,6 +172,7 @@ impl DtlsConnector { } } +#[cfg(feature="async")] #[derive(Debug)] pub enum AsyncConnectError { ErrorStack(ErrorStack), diff --git a/src/lib.rs b/src/lib.rs index 01f1c97..7c3bf13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,9 @@ mod protocol; mod srtp_profile; mod udp_channel; +#[cfg(feature="async")] mod udp_channel_async; +#[cfg(feature="async")] mod dtls_stream_async; pub use self::certificate::Certificate; @@ -32,5 +34,7 @@ pub use self::protocol::Protocol; pub use self::srtp_profile::SrtpProfile; pub use self::udp_channel::{UdpChannel, SyncUdpChannel}; +#[cfg(feature="async")] pub use self::udp_channel_async::{AsyncUdpChannel}; +#[cfg(feature="async")] pub use self::dtls_stream_async::{AsyncDtlsStream}; From 1a6e70482b9b70ce33e03302ff58cb392060d470 Mon Sep 17 00:00:00 2001 From: Alexey Aristov Date: Tue, 21 Jan 2020 23:10:27 +0100 Subject: [PATCH 3/6] move AsyncConnectError to error.rs --- src/dtls_connector.rs | 9 +-------- src/error.rs | 7 +++++++ src/lib.rs | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/dtls_connector.rs b/src/dtls_connector.rs index dc00f5d..3a65ccb 100644 --- a/src/dtls_connector.rs +++ b/src/dtls_connector.rs @@ -8,7 +8,7 @@ use openssl::error::ErrorStack; use std::{fmt, io, io::Write}; #[cfg(feature="async")] -use crate::AsyncDtlsStream; +use crate::{AsyncDtlsStream, AsyncConnectError}; #[cfg(feature="async")] use tokio_openssl; #[cfg(feature="async")] @@ -172,13 +172,6 @@ impl DtlsConnector { } } -#[cfg(feature="async")] -#[derive(Debug)] -pub enum AsyncConnectError { - ErrorStack(ErrorStack), - TokioOpenSsl(tokio_openssl::HandshakeError) -} - impl AsRef for DtlsConnector { fn as_ref(&self) -> &SslConnector { &self.connector diff --git a/src/error.rs b/src/error.rs index ad9f094..671a4ef 100644 --- a/src/error.rs +++ b/src/error.rs @@ -133,3 +133,10 @@ impl FromStr for SrtpProfile { } } } + +#[cfg(feature="async")] +#[derive(Debug)] +pub enum AsyncConnectError { + ErrorStack(ErrorStack), + TokioOpenSsl(tokio_openssl::HandshakeError) +} diff --git a/src/lib.rs b/src/lib.rs index 7c3bf13..3836d75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,8 @@ pub use self::protocol::Protocol; pub use self::srtp_profile::SrtpProfile; pub use self::udp_channel::{UdpChannel, SyncUdpChannel}; +#[cfg(feature="async")] +pub use self::error::{AsyncConnectError}; #[cfg(feature="async")] pub use self::udp_channel_async::{AsyncUdpChannel}; #[cfg(feature="async")] From f9259ca841a5808b3117f12feac6babf4914ee0e Mon Sep 17 00:00:00 2001 From: Alexey Aristov Date: Wed, 22 Jan 2020 00:05:04 +0100 Subject: [PATCH 4/6] fix Identity -> CertifcateIdentity --- examples/udp_socket.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/udp_socket.rs b/examples/udp_socket.rs index 011e45f..3813548 100644 --- a/examples/udp_socket.rs +++ b/examples/udp_socket.rs @@ -6,12 +6,12 @@ use std::{ time::Duration, }; -use udp_dtls::{Certificate, DtlsAcceptor, DtlsConnector, Identity, SrtpProfile}; +use udp_dtls::{Certificate, DtlsAcceptor, DtlsConnector, CertificateIdentity, SrtpProfile}; use udp_dtls::{DtlsAcceptorBuilder, UdpChannel}; fn main() { let buffer = include_bytes!("../test/identity.p12"); - let identity = Identity::from_pkcs12(buffer, "mypass").unwrap(); + let identity = CertificateIdentity::from_pkcs12(buffer, "mypass").unwrap(); let root_ca = include_bytes!("../test/root-ca.der"); let root_ca = Certificate::from_der(root_ca).unwrap(); From 1524fa39d52c42f8a626175727fa88a2a5b2eacd Mon Sep 17 00:00:00 2001 From: Alexey Aristov Date: Wed, 22 Jan 2020 00:05:41 +0100 Subject: [PATCH 5/6] async support for dtls_acceptor --- src/dtls_acceptor.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/dtls_acceptor.rs b/src/dtls_acceptor.rs index 686d57a..306d462 100644 --- a/src/dtls_acceptor.rs +++ b/src/dtls_acceptor.rs @@ -3,6 +3,13 @@ use crate::{DtlsAcceptorBuilder, SyncDtlsStream, HandshakeError, CertificateIden use openssl::ssl::{SslAcceptor, SslMethod}; use std::{fmt, io, result}; +#[cfg(feature="async")] +use crate::{AsyncDtlsStream, AsyncConnectError}; +#[cfg(feature="async")] +use tokio_openssl; +#[cfg(feature="async")] +use tokio::io::{AsyncRead, AsyncWrite}; + /// Acceptor for incoming UDP sessions secured with DTLS. #[derive(Clone)] pub struct DtlsAcceptor(SslAcceptor); @@ -82,6 +89,19 @@ impl DtlsAcceptor { let stream = self.0.accept(stream)?; Ok(SyncDtlsStream::from(stream)) } + + #[cfg(feature="async")] + pub async fn async_accept( + &self, + stream: S + ) -> std::result::Result, AsyncConnectError> + where + S: AsyncRead + AsyncWrite + Unpin + { + let stream = tokio_openssl::accept(&self.0, stream).await.map_err(AsyncConnectError::TokioOpenSsl)?; + + Ok(AsyncDtlsStream::from(stream)) + } } impl From for DtlsAcceptor { From 9c5881bba7e08e7725369d37283acf0fc46fde21 Mon Sep 17 00:00:00 2001 From: Alexey Aristov Date: Wed, 22 Jan 2020 00:06:13 +0100 Subject: [PATCH 6/6] example for async acceptor/connector --- examples/udp_socket_async.rs | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 examples/udp_socket_async.rs diff --git a/examples/udp_socket_async.rs b/examples/udp_socket_async.rs new file mode 100644 index 0000000..7bddcfe --- /dev/null +++ b/examples/udp_socket_async.rs @@ -0,0 +1,74 @@ +use std::time::Duration; +use futures::pin_mut; +use tokio::{net, time, io::{AsyncReadExt, AsyncWriteExt}}; +use udp_dtls::{Certificate, DtlsAcceptor, DtlsConnector, CertificateIdentity, SrtpProfile, AsyncUdpChannel}; + +#[tokio::main] +async fn main() { + let buffer = include_bytes!("../test/identity.p12"); + let identity = CertificateIdentity::from_pkcs12(buffer, "mypass").unwrap(); + + let root_ca = include_bytes!("../test/root-ca.der"); + let root_ca = Certificate::from_der(root_ca).unwrap(); + + let acceptor = DtlsAcceptor::builder(identity).build().unwrap(); + let connector = DtlsConnector::builder() + .add_srtp_profile(SrtpProfile::Aes128CmSha180) + .add_srtp_profile(SrtpProfile::AeadAes256Gcm) + .add_root_certificate(root_ca) + .build() + .unwrap(); + + let server = net::UdpSocket::bind("127.0.0.1:0").await.unwrap(); + let client = net::UdpSocket::bind("127.0.0.1:0").await.unwrap(); + + let server_addr = server.local_addr().unwrap(); + let client_addr = client.local_addr().unwrap(); + + let server_channel = AsyncUdpChannel { + socket: server, + remote_addr: client_addr, + }; + + let client_channel = AsyncUdpChannel { + socket: client, + remote_addr: server_addr, + }; + + let connector_task = async move { + let stream = connector.async_connect("foobar.com", client_channel).await.unwrap(); + + pin_mut!(stream); + loop { + let buf = b"hello"; + stream.write_all(buf).await.unwrap(); + + time::delay_for(Duration::from_millis(30)).await; + } + }; + + let acceptor_task = async move { + let stream = acceptor.async_accept(server_channel).await.unwrap(); + let mut count = 0; + + pin_mut!(stream); + loop { + let mut received = [0; 5]; + + stream.read_exact(&mut received).await.unwrap(); + + println!( + "{:?} {:?}", + count, + String::from_utf8_lossy(received.as_ref()) + ); + + count = count + 1; + + time::delay_for(Duration::from_millis(2)).await; + } + }; + + tokio::spawn(connector_task); + tokio::spawn(acceptor_task).await.unwrap(); +}