diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..7d1f9c5 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,6 @@ +[target.arm-unknown-linux-gnueabihf] +linker = "arm-linux-gnueabihf-gcc" +[target.armv7-unknown-linux-gnueabihf] +linker = "arm-linux-gnueabihf-gcc" +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40ee8c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +.idea +.vscode +perf.data* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6d46fc8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +All visible changes will be documented here. This project adheres to Semantic Versioning. + +## [Unreleased] + +- Support for c in a library +- Gracefull handling of socket/sleeps/network delays +- Pass in sleep function + +## [0.1.0] - 2023-02-15 + +### Added + +- Initial tftp binary and library realese \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..27cf932 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1215 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" +dependencies = [ + "crypto-common", + "generic-array", + "heapless", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "ar" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "atomic-polyfill" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cargo-deb" +version = "1.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f48b91ed2617f2860bd5ab8f1d5b817147a38ebb1b8ecb2fa1588618ab863a" +dependencies = [ + "ar", + "cargo_toml", + "crossbeam-channel", + "env_logger", + "flate2", + "getopts", + "glob", + "itertools", + "log", + "md5", + "num_cpus", + "quick-error", + "rayon", + "regex", + "serde", + "serde_json", + "tar", + "tempfile", + "toml", + "xz2", +] + +[[package]] +name = "cargo_toml" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfbc36312494041e2cdd5f06697b7e89d4b76f42773a0b5556ac290ff22acc2" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "cc" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clap" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.45.0", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys 0.42.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[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-macro2" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.42.0", +] + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "tftp" +version = "0.1.0" +dependencies = [ + "arrayvec", + "base64", + "chacha20poly1305", + "hash32", + "heapless", + "log", + "rand", + "vfs", + "x25519-dalek", +] + +[[package]] +name = "tftp-binary" +version = "0.1.0" +dependencies = [ + "cargo-deb", + "clap", + "env_logger", + "log", + "polling", + "rand", + "tftp", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vfs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded573c92d7b32013bdab82676be59f56106895e837504568f32804980ec7868" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +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-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 = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "x25519-dalek" +version = "2.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] + +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d236eac --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "tftp" +version = "0.1.0" +edition = "2021" + +[profile.release] +strip="debuginfo" + +[workspace] +members = [ + "binary" +] + +[dependencies] +log = "0.4" +# TODO remove once heapless retain is available and results must be used fixed +arrayvec = { version = "0.7", optional = false, default-features = false} +heapless = { version = "0.7", optional = false, default-features = false} +base64 = { version = "0.21", optional = true, default-features = false} +x25519-dalek = { version = "2.0.0-pre.0", optional = true, default-features = false, features = ["u64_backend"]} +chacha20poly1305 = { version = "0.10", optional = true, default-features = false, features = ["heapless", "getrandom"]} +# heapless depends on 0.2.1 +hash32 = "0.2.1" +rand = { version = "0.8", optional = false, default-features = false, features = ["getrandom"]} + +[dev-dependencies] +rand = "0.8" +vfs = "0.9" + +[features] +default = ["std", "alloc", "encryption"] +std = ["x25519-dalek?/std"] +alloc = ["chacha20poly1305?/alloc"] +encryption = ["x25519-dalek", "chacha20poly1305", "base64"] +seek = [] +stack_large_window = [] \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fe10e1f --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ + +The MIT License (MIT) + +Copyright (c) 2016 Michael Murphy +Copyright (c) 2017 Kornel LesiƄski + +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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c620e76 --- /dev/null +++ b/README.md @@ -0,0 +1,178 @@ +# tftp + +Simple tftp protocol client and server implementation in rust. + +Adheres to RFCs: + +- [rfc1350](https://www.rfc-editor.org/rfc/rfc1350) +- [rfc2347](https://www.rfc-editor.org/rfc/rfc2347) +- [rfc2348](https://www.rfc-editor.org/rfc/rfc2348) +- [rfc2349](https://www.rfc-editor.org/rfc/rfc2349) +- [rfc7440](https://www.rfc-editor.org/rfc/rfc7440) + +Additionaly public/private keys and xchacha20poly1305 encryption can be used to +encrypt traffic or data. + +## Installing + +Install deb + +``` +wget https://github.com/songokas/tftp/releases/download/0.1.0/tftp_0.1.0_amd64.deb && sudo apt install ./tftp_0.1.0_amd64.deb +``` + +Download binary + +https://github.com/songokas/tftp/releases + +Install from source + +```bash +cargo install --bins --root=~/bin/ --git=https://github.com/songokas/tftp +``` + +## Getting started + +Run the server and send a file + +```bash +tftp server 127.0.0.1:9000 /tmp +echo "hello" | tftp send 127.0.0.1:9000 /dev/stdin +``` + +## Features + +* low memory consumption +* supports tsize, blksize, timeout, windowsize options +* send/receive encrypted files +* authorization of public keys +* optional stack only functionality (currently lib only) +* compatible with third party clients,servers +* large file support + +### Configuration + +Run help to see all available options + +```bash +tftp server --help +tftp send --help +tftp receive --help +``` + +#### Using encryption with server + +As long as the binary is compiled with feature=encryption optional encryption will be enabled automatically + +server will generate a random key per client if no private key is provided + +```bash +tftp server 127.0.0.1:9000 /tmp +``` + +restrict who is able to access the server + +```bash +# ~/.authorized_keys base64 encoded key per line 1TGOop6cYn8meO0bOtnRbsQ4tfd0zRfGJhaMGCZVZ6M= +tftp server 127.0.0.1:9000 /tmp --private-key `openssl rand -base64 32` --authorized-keys ~/.authorized_keys +``` + +#### Using encryption with client + +Encryption is used based on `--encryption-level` argument (default: optional-protocol) +Client should be able to communicate even if the server does not support encryption. + +client will exchange public keys and encrypt the traffic afterwards + +```bash +echo "hello" | tftp send 127.0.0.1:9000 /dev/stdin --encryption-level protocol +``` + +client will exchange public keys and encrypt the data traffic + +```bash +echo "hello" | tftp send 127.0.0.1:9000 /dev/stdin --encryption-level data +``` + +if the server public key is known and `--encryption-level protocol` is used client will encrypt all traffic from the start + +```bash +echo "hello" | tftp send 127.0.0.1:9000 /dev/stdin --server-public-key 1TGOop6cYn8meO0bOtnRbsQ4tfd0zRfGJhaMGCZVZ6M= --encryption-level protocol +``` + +#### Allow port change if needed for third party tftp + +server + +```bash +tftp server 127.0.0.1:9000 /tmp --require-server-port-change +``` + +client + +```bash +echo "hello" | tftp send 127.0.0.1:9000 /dev/stdin --allow-server-port-change +``` + +### Stats + +``` + Send 100Mb + +----------------------------------------------------------------------------------------------------------+ + | + + + + + + | + 7 |-+ +-| + | | + | | + | | + | | + 6.5 |-+ +-| + | | + | | + | | + 6 |-+ +-| +Time | | + | | + | | + 5.5 |-+ +-| + | x | + | | + | x x x | + 5 |-+ x x x x +-| + | x x x | + | | + | + + + + + + | + 4.5 +----------------------------------------------------------------------------------------------------------+ + 0 10 20 30 40 50 60 + WindowSize + + + Receive 100Mb + +------------------------------------------------------------------------------------------------------------+ + | + + + + + + | + 7 |-+ +-| + | | + | | + 6 |-+ +-| + | x | + | | + 5 |-+ +-| + | | + | | + 4 |-+ +-| +Time | | + | | + 3 |-+x +-| + | | + | | + 2 |-+ x +-| + | | + | x x | + 1 |-+ x x x x +-| + | x x | + | + + + + + + | + 0 +------------------------------------------------------------------------------------------------------------+ + 0 10 20 30 40 50 60 + WindowSize +``` + +[More info](./info) \ No newline at end of file diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs new file mode 100644 index 0000000..e3adcdc --- /dev/null +++ b/benches/benchmarks.rs @@ -0,0 +1,206 @@ +#![feature(test)] +extern crate test; + +use std::collections::BTreeMap; + +use rand::Rng; +use test::Bencher; +use tftp::config::MAX_BUFFER_SIZE; + +#[bench] +fn test_packet_to_bytes_with_iter(b: &mut Bencher) { + b.iter(|| { + let random_bytes: Vec = (0..MAX_BUFFER_SIZE - 4) + .map(|_| rand::random::()) + .collect(); + let data_packet: Vec = 1_u16 + .to_be_bytes() + .into_iter() + .chain(random_bytes.into_iter()) + .collect(); + let _packet: Vec = 5_u16 + .to_be_bytes() + .into_iter() + .chain(data_packet.into_iter()) + .collect(); + }); +} + +#[bench] +fn test_packet_to_bytes_with_concat(b: &mut Bencher) { + b.iter(|| { + let random_bytes: Vec = (0..MAX_BUFFER_SIZE - 4) + .map(|_| rand::random::()) + .collect(); + let data_packet: Vec = [1_u16.to_be_bytes().to_vec(), random_bytes].concat(); + let _packet: Vec = [5_u16.to_be_bytes().to_vec(), data_packet].concat(); + }); +} + +#[bench] +fn test_packet_to_bytes_with_extend(b: &mut Bencher) { + b.iter(|| { + let random_bytes: Vec = (0..MAX_BUFFER_SIZE - 4) + .map(|_| rand::random::()) + .collect(); + let mut data_packet: Vec = 1_u16.to_be_bytes().to_vec(); + data_packet.extend(random_bytes); + let mut packet: Vec = 5_u16.to_be_bytes().to_vec(); + packet.extend(data_packet); + }); +} + +#[bench] +fn test_vector_resizing(b: &mut Bencher) { + let mut vec: Vec = Vec::new(); + vec.resize(MAX_BUFFER_SIZE as usize, 0); + b.iter(|| { + vec.resize(MAX_BUFFER_SIZE as usize, 0); + vec.truncate(rand::random::() as usize); + }); +} + +// TODO slow +#[bench] +fn test_heapless_vector_resizing(b: &mut Bencher) { + let mut vec: heapless::Vec = heapless::Vec::new(); + vec.resize(MAX_BUFFER_SIZE as usize, 0).unwrap(); + b.iter(|| { + vec.resize(MAX_BUFFER_SIZE as usize, 0).unwrap(); + vec.truncate(rand::random::() as usize); + }); +} + +#[bench] +fn test_heapless_vector_set_len(b: &mut Bencher) { + let mut vec: heapless::Vec = heapless::Vec::new(); + vec.resize(MAX_BUFFER_SIZE as usize, 0).unwrap(); + b.iter(|| { + unsafe { vec.set_len(MAX_BUFFER_SIZE as usize) }; + vec.truncate(rand::random::() as usize); + }); +} + +#[bench] +fn test_array_vector_resizing(b: &mut Bencher) { + let mut vec: arrayvec::ArrayVec = arrayvec::ArrayVec::new(); + // no resize + unsafe { vec.set_len(MAX_BUFFER_SIZE as usize) }; + b.iter(|| { + unsafe { vec.set_len(MAX_BUFFER_SIZE as usize) }; + vec.truncate(rand::random::() as usize); + }); +} + +#[bench] +fn test_btree_retrieve_256(b: &mut Bencher) { + let mut map = BTreeMap::new(); + let mut i = 0; + while i <= u8::MAX { + map.insert(i, true); + + if i == u8::MAX { + break; + } + i += 1; + } + + b.iter(|| { + map.get(&rand::random::()).unwrap(); + }); +} + +#[bench] +fn test_arrayvec_retrieve_256(b: &mut Bencher) { + let mut map = arrayvec::ArrayVec::::new(); + let mut i = 0; + while i <= u8::MAX { + map.push(i); + if i == u8::MAX { + break; + } + i += 1; + } + + b.iter(|| { + let random_index = rand::random::(); + map.iter().find(|i| *i == &random_index).unwrap(); + }); +} + +#[bench] +fn test_btree_retrieve_20(b: &mut Bencher) { + const SIZE: usize = 20; + let mut map = BTreeMap::new(); + let mut i: u8 = 0; + while i as usize <= SIZE { + map.insert(i, true); + if i as usize == SIZE - 1 { + break; + } + i += 1; + } + let mut rng = rand::thread_rng(); + b.iter(|| { + let random_index = rng.gen_range(0..19); + map.get(&random_index).unwrap(); + }); +} + +#[bench] +fn test_arrayvec_retrieve_20(b: &mut Bencher) { + const SIZE: usize = 20; + let mut map = arrayvec::ArrayVec::::new(); + let mut i: u8 = 0; + while i as usize <= SIZE { + map.push(i); + if i as usize == SIZE - 1 { + break; + } + i += 1; + } + let mut rng = rand::thread_rng(); + b.iter(|| { + let random_index = rng.gen_range(0..19); + map.iter().find(|i| *i == &random_index).unwrap(); + }); +} + +#[cfg(feature = "encryption")] +#[bench] +fn test_encrypt_decrypt(b: &mut Bencher) { + use tftp::{config::MAX_DATA_BLOCK_SIZE, types::DataBuffer}; + + let encryptor = create_encryptor(); + let mut rng = rand::thread_rng(); + let mut blocks = Vec::new(); + for _ in 0..1000 { + let bytes: Vec = (0..MAX_DATA_BLOCK_SIZE).map(|_| rng.gen::()).collect(); + let data: DataBuffer = bytes.into_iter().collect(); + blocks.push(data); + } + + b.iter(|| { + let random_index = rng.gen_range(0..blocks.len() - 1); + encryptor.encrypt(&mut blocks[random_index]).unwrap(); + encryptor.decrypt(&mut blocks[random_index]).unwrap(); + }); +} + +#[cfg(feature = "encryption")] +fn create_encryptor() -> tftp::encryption::Encryptor { + use chacha20poly1305::{KeyInit, XChaCha20Poly1305}; + tftp::encryption::Encryptor { + cipher: XChaCha20Poly1305::new( + &[ + 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, + 200, 17, 22, 29, 93, 32, 1, + ] + .into(), + ), + nonce: [ + 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, + ] + .into(), + } +} diff --git a/binary/Cargo.toml b/binary/Cargo.toml new file mode 100644 index 0000000..0633311 --- /dev/null +++ b/binary/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "tftp-binary" +version = "0.1.0" +edition = "2021" + +authors = ["Tomas Jakstas "] +description = "Tftp server and client" +homepage = "https://github.com/songokas/tftp" +repository = "https://github.com/songokas/tftp" +license = "../LICENSE" +readme = "../README.md" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# std compile time requirement +clap = { version = "4", features = ["derive"] } +env_logger = "0.10" +log = "0.4" +tftp = { path = "..", default-features = false} +rand = { version = "0.8", optional = false, default-features = false, features = ["getrandom"]} +# std compile time requirement +polling = "2" + +[dev-dependencies] +rand = "0.8" +env_logger = "0.10" + +[features] +default = ["std", "alloc", "encryption"] +std = ["tftp/std", "polling/std"] +alloc = ["tftp/alloc"] +encryption = ["tftp/encryption"] +seek = ["tftp/seek"] +stack_large_window = ["tftp/stack_large_window"] + +[[bin]] +name = "tftp" +path = "src/main.rs" + + + +[build-dependencies] +cargo-deb = "1" + +[package.metadata.deb] +name = "tftp" +maintainer = "Tomas Jakstas " +copyright = "2023, Tomas Jakstas " +extended-description = """\ +Simple tftp client and server with optional encryption\ +""" +depends = "$auto" +section = "utility" +priority = "optional" +maintainer-scripts = "../builder/debian" +assets = [ + ["target/release/tftp", "usr/bin/", "755"], + ["../README.md", "usr/share/doc/tftp/README", "644"], + ["../builder/debian/service", "lib/systemd/system/tftp.service", "644"], +] diff --git a/binary/src/cli.rs b/binary/src/cli.rs new file mode 100644 index 0000000..a77d23a --- /dev/null +++ b/binary/src/cli.rs @@ -0,0 +1,272 @@ +use core::{cmp::min, time::Duration}; +use std::net::ToSocketAddrs; + +use clap::{Parser, Subcommand}; +use tftp::{ + client::ClientConfig, + config::{ + DEFAULT_DATA_BLOCK_SIZE, DEFAULT_WINDOW_SIZE, EXTENSION_BLOCK_SIZE_MIN, + EXTENSION_TIMEOUT_SIZE_MAX, EXTENSION_TIMEOUT_SIZE_MIN, EXTENSION_WINDOW_SIZE_MIN, + MAX_BLOCKS_READER, MAX_BLOCKS_WRITER, MAX_CLIENTS, MAX_DATA_BLOCK_SIZE, + RETRY_PACKET_TIMEOUT, + }, + encryption::{decode_private_key, decode_public_key}, + error::BoxedError, + key_management::{get_from_known_hosts, read_authorized_keys}, + server::ServerConfig, + types::{DefaultString, ExtensionValue, FilePath, ShortString}, +}; + +use crate::io::create_buff_reader; + +pub type BinError = Box; +pub type BinResult = Result; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct Args { + #[command(subcommand)] + pub command: Commands, + #[arg(short, long, default_value = "info")] + pub verbosity: DefaultString, +} + +#[derive(Parser, Debug, Clone)] +pub struct ClientCliConfig { + pub endpoint: DefaultString, + + #[arg(short, long, default_value = "0.0.0.0:0")] + pub listen: DefaultString, + + #[arg( + long, + default_value_t = 15000, + help = "Request time out in milliseconds. default: 15000" + )] + pub request_timeout: u64, + + #[arg(long, default_value_t = MAX_DATA_BLOCK_SIZE as u64, value_parser = clap::value_parser!(u64).range((EXTENSION_BLOCK_SIZE_MIN as u64)..=(MAX_DATA_BLOCK_SIZE as u64)))] + pub block_size: u64, + + #[arg(long, default_value_t = DEFAULT_WINDOW_SIZE as u64, value_parser = clap::value_parser!(u64).range((EXTENSION_WINDOW_SIZE_MIN as u64)..=(MAX_BLOCKS_READER as u64)))] + pub window_size: u64, + + #[arg( + long, + default_value_t = RETRY_PACKET_TIMEOUT.as_secs(), + value_parser = clap::value_parser!(u64).range((EXTENSION_TIMEOUT_SIZE_MIN as u64)..(EXTENSION_TIMEOUT_SIZE_MAX as u64)), + help = "Resend packet after timeout. default: 1 second" + )] + pub retry_timeout: u64, + + #[arg( + long, + default_value_t = 10485760, + help = "Max file size to receive. default: 10Mb" + )] + pub max_file_size: u64, + + #[cfg(feature = "encryption")] + #[arg( + long, + default_value = "optional-protocol", + help = "Available values protocol, data, optional-data, optional-protocol, none" + )] + pub encryption_level: ShortString, + + #[cfg(feature = "encryption")] + #[arg(long)] + pub private_key: Option, + #[cfg(feature = "encryption")] + #[arg(long)] + pub server_public_key: Option, + #[cfg(feature = "encryption")] + #[arg(long)] + pub known_hosts: Option, + + #[arg(long)] + pub allow_server_port_change: bool, +} + +#[derive(Parser, Debug, Clone)] +pub struct ServerCliConfig { + pub listen: DefaultString, + + pub directory: FilePath, + + #[arg(short, long)] + pub allow_overwrite: bool, + + #[arg(long, default_value_t = MAX_CLIENTS as u64, value_parser = clap::value_parser!(u64).range(1..=(MAX_CLIENTS as u64)))] + pub max_connections: u64, + + #[arg(long, default_value_t = 1 as u64, value_parser = clap::value_parser!(u64).range(1..=(MAX_BLOCKS_READER as u64)))] + pub max_blocks_in_queue_reader: u64, + + #[arg(long, default_value_t = 1 as u64, value_parser = clap::value_parser!(u64).range(1..=(MAX_BLOCKS_WRITER as u64)))] + pub max_blocks_in_queue_writer: u64, + + #[arg(long, default_value_t = min(MAX_BLOCKS_WRITER, MAX_BLOCKS_READER) as u64, value_parser = clap::value_parser!(u64).range(1..=(min(MAX_BLOCKS_WRITER, MAX_BLOCKS_READER) as u64)))] + pub max_window_size: u64, + + #[arg( + long, + default_value_t = 15000, + help = "Request time out in milliseconds. default: 15000" + )] + pub request_timeout: u16, + + #[arg( + long, + default_value_t = 10485760, + help = "Max file size to receive. default: 10Mb" + )] + pub max_file_size: u64, + + #[arg(long, default_value_t = MAX_DATA_BLOCK_SIZE as u64, value_parser = clap::value_parser!(u64).range((EXTENSION_BLOCK_SIZE_MIN as u64)..=(MAX_DATA_BLOCK_SIZE as u64)))] + pub max_block_size: u64, + + #[cfg(feature = "encryption")] + #[arg(long)] + pub authorized_keys: Option, + #[cfg(feature = "encryption")] + #[arg(long)] + pub private_key: Option, + + #[cfg(feature = "encryption")] + #[arg(long, help = "Require that connection be fully encrypted")] + pub required_full_encryption: Option, + + #[arg(long)] + pub require_server_port_change: bool, +} + +#[derive(Subcommand, Debug)] +pub enum Commands { + Send { + #[clap(flatten)] + config: ClientCliConfig, + + #[arg(value_name = "FILE")] + local_path: FilePath, + + #[arg(short, long)] + remote_path: Option, + + #[arg(long, default_value_t = 1 as u64, value_parser = clap::value_parser!(u64).range(1..=(MAX_BLOCKS_READER as u64)))] + max_blocks_in_queue: u64, + }, + + Receive { + #[clap(flatten)] + config: ClientCliConfig, + + #[arg(long)] + local_path: Option, + + #[arg(value_name = "FILE")] + remote_path: FilePath, + + #[arg(long, default_value_t = 1 as u64, value_parser = clap::value_parser!(u64).range(1..=(MAX_BLOCKS_WRITER as u64)))] + max_blocks_in_queue: u64, + }, + + Server(ServerCliConfig), +} + +impl ClientCliConfig { + pub fn try_into(self, max_blocks_in_memory: u16) -> BinResult { + #[cfg(feature = "encryption")] + let remote_public_key = match (&self.server_public_key, &self.known_hosts) { + (Some(p), _) => decode_public_key(p.as_bytes()) + .map_err(|e| BinError::from(e.to_string()))? + .into(), + (_, Some(p)) => get_from_known_hosts( + create_buff_reader(p.as_str()).map_err(|e| BinError::from(e.to_string()))?, + &self.endpoint, + ) + .map_err(|e| BinError::from(e.to_string()))?, + _ => None, + }; + #[cfg(not(feature = "encryption"))] + let remote_public_key = None; + + #[cfg(feature = "encryption")] + let private_key = self + .private_key + .as_deref() + .map(crate::io::read_private_value_or_file) + .transpose() + .map_err(|e| BinError::from(e.to_string()))?; + #[cfg(not(feature = "encryption"))] + let private_key = None; + + let endpoint = self + .endpoint + .as_str() + .to_socket_addrs()? + .next() + .ok_or_else(|| BinError::from("Unable to resolve endpoint address"))?; + #[cfg(not(feature = "std"))] + let endpoint = crate::socket::std_to_socket_addr(endpoint); + Ok(ClientConfig { + listen: self.listen, + endpoint, + max_blocks_in_memory, + request_timeout: Duration::from_millis(self.request_timeout), + max_file_size: self.max_file_size, + private_key, + remote_public_key, + allow_server_port_change: self.allow_server_port_change, + }) + } +} + +impl ServerCliConfig { + pub fn try_into(self) -> BinResult { + let listen = self + .listen + .as_str() + .to_socket_addrs()? + .next() + .ok_or_else(|| BinError::from("Unable to resolve listen address"))?; + #[cfg(not(feature = "std"))] + let listen = crate::socket::std_to_socket_addr(listen); + Ok(ServerConfig { + listen, + directory: self.directory, + allow_overwrite: self.allow_overwrite, + max_queued_blocks_reader: self.max_blocks_in_queue_reader as u16, + max_queued_blocks_writer: self.max_blocks_in_queue_writer as u16, + max_window_size: self.max_window_size as u16, + request_timeout: Duration::from_millis(self.request_timeout as u64), + max_connections: self.max_connections as u16, + max_file_size: self.max_file_size, + max_block_size: self.max_block_size as u16, + #[cfg(feature = "encryption")] + private_key: self + .private_key + .as_deref() + .map(crate::io::read_private_value_or_file) + .transpose() + .map_err(|e| BinError::from(e.to_string()))?, + #[cfg(not(feature = "encryption"))] + private_key: None, + #[cfg(feature = "encryption")] + required_full_encryption: self + .required_full_encryption + .unwrap_or(self.authorized_keys.is_some()), + #[cfg(not(feature = "encryption"))] + required_full_encryption: false, + #[cfg(feature = "encryption")] + authorized_keys: self + .authorized_keys + .map(|p| read_authorized_keys(create_buff_reader(p.as_str())?)) + .transpose() + .map_err(|e| BinError::from(e.to_string()))?, + #[cfg(not(feature = "encryption"))] + authorized_keys: None, + require_server_port_change: self.require_server_port_change, + }) + } +} diff --git a/binary/src/io.rs b/binary/src/io.rs new file mode 100644 index 0000000..e3e0f72 --- /dev/null +++ b/binary/src/io.rs @@ -0,0 +1,203 @@ +use std::{fs::File, path::PathBuf}; + +use tftp::{ + config::{ConnectionOptions, MAX_EXTENSION_VALUE_SIZE}, + encryption::{decode_private_key, PrivateKey}, + error::{BoxedResult, EncryptionError}, + server::ServerConfig, + std_compat::io, + types::FilePath, +}; + +pub fn create_writer(path: &FilePath) -> BoxedResult { + let file = File::create(path.as_str()).map_err(from_io_err)?; + #[cfg(not(feature = "std"))] + let file = StdCompatFile(file); + Ok(file) +} + +pub fn create_reader(path: &FilePath) -> BoxedResult<(Option, StdCompatFile)> { + let file = File::open(path.as_str()).map_err(from_io_err)?; + let file_size = file.metadata().map_err(from_io_err)?.len(); + #[cfg(not(feature = "std"))] + let file = StdCompatFile(file); + Ok(((file_size > 0).then(|| file_size), file)) +} + +pub fn create_server_reader( + path: &FilePath, + config: &ServerConfig, +) -> BoxedResult<(Option, StdCompatFile)> { + let dir: PathBuf = config.directory.as_str().parse()?; + let path = dir.join(path.as_str()); + create_reader(&std_into_path(path)) +} + +pub fn create_server_writer(path: &FilePath, config: &ServerConfig) -> BoxedResult { + use std::fs::{create_dir_all, OpenOptions}; + // TODO alloc in stack PathBuf + let dir: PathBuf = config.directory.as_str().parse()?; + let path: PathBuf = dir.join(path.as_str()); + if let Some(dir) = path.parent() { + if !dir.is_dir() { + create_dir_all(dir).map_err(from_io_err)? + } + }; + let mut options = OpenOptions::new(); + if config.allow_overwrite { + options.write(true).create(true).truncate(true) + } else { + options.write(true).create_new(true) + }; + let file = options.open(path).map_err(from_io_err)?; + #[cfg(not(feature = "std"))] + let file = StdCompatFile(file); + + Ok(file) +} + +#[allow(dead_code)] +pub fn create_simple_reader(path: &str) -> BoxedResult { + let file = File::open(path).map_err(from_io_err)?; + #[cfg(not(feature = "std"))] + let file = StdCompatFile(file); + Ok(file) +} + +#[cfg(feature = "encryption")] +pub fn read_private_value_or_file(private: &str) -> Result { + #[cfg(feature = "std")] + use std::io::Read; + + #[cfg(not(feature = "std"))] + use tftp::std_compat::io::Read; + let result = decode_private_key(private.as_bytes()); + + if result.is_err() { + if let Ok(mut reader) = create_simple_reader(private) { + let mut buf = [0; MAX_EXTENSION_VALUE_SIZE as usize]; + if let Ok(read) = reader.read(&mut buf) { + if let Ok(p) = decode_private_key(&buf[..read]) { + return Ok(p); + } + } + } + } + result +} + +#[cfg(feature = "std")] +pub type StdCompatFile = std::fs::File; +#[cfg(not(feature = "std"))] +pub struct StdCompatFile(pub std::fs::File); + +#[cfg(not(feature = "std"))] +impl io::Write for StdCompatFile { + fn write(&mut self, buf: &[u8]) -> io::Result { + use std::io::Write; + self.0.write(buf).map_err(from_io_err) + } + + fn write_fmt(&mut self, fmt: core::fmt::Arguments<'_>) -> io::Result<()> { + use std::io::Write; + self.0.write_fmt(fmt).map_err(from_io_err) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[cfg(not(feature = "std"))] +impl io::Seek for StdCompatFile { + fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + use std::io::Seek; + let pos = match pos { + io::SeekFrom::Start(p) => std::io::SeekFrom::Start(p), + io::SeekFrom::Current(p) => std::io::SeekFrom::Current(p), + io::SeekFrom::End(p) => std::io::SeekFrom::End(p), + }; + self.0 + .seek(pos) + .map_err(|_| tftp::std_compat::io::Error::from(tftp::std_compat::io::ErrorKind::Other)) + } +} + +#[cfg(not(feature = "std"))] +impl io::Read for StdCompatFile { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + use std::io::Read; + self.0.read(buf).map_err(from_io_err) + } +} + +pub fn from_io_err(err: std::io::Error) -> io::Error { + #[cfg(feature = "std")] + return err; + #[cfg(not(feature = "std"))] + io::Error::from(match err.kind() { + std::io::ErrorKind::NotFound => io::ErrorKind::NotFound, + std::io::ErrorKind::PermissionDenied => io::ErrorKind::PermissionDenied, + std::io::ErrorKind::ConnectionRefused => io::ErrorKind::ConnectionRefused, + std::io::ErrorKind::ConnectionReset => io::ErrorKind::ConnectionReset, + std::io::ErrorKind::ConnectionAborted => io::ErrorKind::ConnectionAborted, + std::io::ErrorKind::NotConnected => io::ErrorKind::NotConnected, + std::io::ErrorKind::AddrInUse => io::ErrorKind::AddrInUse, + std::io::ErrorKind::BrokenPipe => io::ErrorKind::BrokenPipe, + std::io::ErrorKind::AlreadyExists => io::ErrorKind::AlreadyExists, + std::io::ErrorKind::WouldBlock => io::ErrorKind::WouldBlock, + std::io::ErrorKind::InvalidInput => io::ErrorKind::InvalidInput, + std::io::ErrorKind::InvalidData => io::ErrorKind::InvalidData, + std::io::ErrorKind::TimedOut => io::ErrorKind::TimedOut, + std::io::ErrorKind::WriteZero => io::ErrorKind::WriteZero, + std::io::ErrorKind::Interrupted => io::ErrorKind::Interrupted, + std::io::ErrorKind::UnexpectedEof => io::ErrorKind::UnexpectedEof, + std::io::ErrorKind::OutOfMemory => io::ErrorKind::OutOfMemory, + _ => io::ErrorKind::Other, + }) +} + +#[allow(dead_code)] +pub fn create_buff_reader(path: &str) -> io::Result { + let file = std::io::BufReader::new( + File::options() + .create(true) + .read(true) + .write(true) + .open(path) + .map_err(from_io_err)?, + ); + #[cfg(not(feature = "std"))] + let file = StdBufReader(file); + Ok(file) +} + +#[cfg(feature = "std")] +pub type StdBufReader = std::io::BufReader; +#[cfg(not(feature = "std"))] +pub struct StdBufReader(std::io::BufReader); + +#[cfg(not(feature = "std"))] +impl tftp::std_compat::io::BufRead for StdBufReader { + fn read_line( + &mut self, + buf: &mut tftp::types::DefaultString, + ) -> tftp::std_compat::io::Result { + use std::io::BufRead; + // TODO alloc in stack + let mut s = std::string::String::with_capacity(buf.capacity()); + let result = self.0.read_line(&mut s).map_err(from_io_err); + let _result = buf.push_str(s.as_str()); + #[cfg(not(feature = "alloc"))] + _result.map_err(|_| io::Error::from(io::ErrorKind::InvalidData))?; + result + } +} + +#[allow(unused_must_use)] +pub fn std_into_path(path: PathBuf) -> FilePath { + let mut f = FilePath::new(); + // TODO alloc in stack + let _result = f.push_str(&path.to_string_lossy().to_string()); + f +} diff --git a/binary/src/main.rs b/binary/src/main.rs new file mode 100644 index 0000000..4fa2aa3 --- /dev/null +++ b/binary/src/main.rs @@ -0,0 +1,680 @@ +#![allow(unused_variables)] +#![allow(unused_imports)] + +mod cli; +mod io; +mod socket; + +use core::time::Duration; +use std::{cmp::min, path::Path}; + +use clap::Parser; +use cli::ClientCliConfig; +use env_logger::{Builder, Env}; +use log::{debug, error, warn}; +use rand::rngs::OsRng; +use tftp::{ + client::{receive_file, send_file}, + config::{ConnectionOptions, MAX_EXTENSION_VALUE_SIZE}, + encryption::{ + decode_private_key, decode_public_key, EncryptionKeys, EncryptionLevel, PrivateKey, + PublicKey, + }, + error::{BoxedResult, EncryptionError}, + key_management::{append_to_known_hosts, get_from_known_hosts}, + server::server, + std_compat::{ + io::{Read, Seek, Write}, + time::Instant, + }, + types::FilePath, +}; + +use crate::{ + cli::{Args, BinError, BinResult, Commands}, + io::{create_reader, create_server_reader, create_server_writer, create_writer, *}, + socket::*, +}; + +// tftp send localhost:3000 /tmp/a --remote-path long/a +// tftp receive localhost:3000 long/a --local-path /tmp/a +// tftp server localhost:300 /tmp --allow-overwrite +fn main() -> BinResult<()> { + let args = Args::parse(); + Builder::from_env(Env::default().default_filter_or(args.verbosity.as_str())) + .format_target(cfg!(debug_assertions)) + .init(); + + match args.command { + Commands::Send { + local_path, + remote_path, + max_blocks_in_queue, + config, + } => start_send( + local_path, + remote_path, + config, + max_blocks_in_queue as u16, + create_reader, + ) + .map(|_| ()), + + Commands::Receive { + config, + local_path, + remote_path, + max_blocks_in_queue, + } => start_receive( + local_path, + remote_path, + config, + max_blocks_in_queue as u16, + create_writer, + ) + .map(|_| ()), + Commands::Server(config) => { + let config = config.try_into()?; + server( + config, + create_server_reader, + create_server_writer, + create_socket, + instant_callback, + OsRng, + ) + .map_err(|e| BinError::from(e.to_string())) + } + } +} + +fn start_send( + local_path: FilePath, + remote_path: Option, + config: ClientCliConfig, + max_blocks_in_queue: u16, + create_reader: CreateReader, +) -> BinResult +where + R: Read + Seek, + CreateReader: Fn(&FilePath) -> BoxedResult<(Option, R)>, +{ + let socket = + create_socket(config.listen.as_str(), 1).map_err(|e| BinError::from(e.to_string()))?; + + let options = ConnectionOptions { + block_size: config.block_size as u16, + retry_packet_after_timeout: Duration::from_secs(config.retry_timeout), + file_size: None, + encryption_keys: None, + #[cfg(feature = "encryption")] + encryption_level: config + .encryption_level + .parse() + .map_err(|_| BinError::from("Invalid encryption level specified"))?, + #[cfg(not(feature = "encryption"))] + encryption_level: EncryptionLevel::None, + window_size: config.window_size as u16, + }; + #[cfg(feature = "encryption")] + let known_hosts_file = config.known_hosts.clone(); + #[cfg(not(feature = "encryption"))] + let known_hosts_file: Option = None; + let endpoint = config.endpoint.clone(); + + let remote_path = match remote_path { + Some(p) => p, + None => Path::new(local_path.as_str()) + .file_name() + .ok_or_else(|| "Invalid local filename")? + .to_string_lossy() + .parse() + .expect("Invalid local file name"), + }; + send_file( + config.try_into(max_blocks_in_queue)?, + local_path, + remote_path, + options, + create_reader, + socket, + instant_callback, + OsRng, + ) + .map(|(total, _remote_key)| { + debug!("Client total sent {}", total); + let file = known_hosts_file.as_ref().map(|s| s.as_str()); + handle_hosts_file(file, _remote_key, &endpoint); + total + }) + .map_err(|e| BinError::from(e.to_string())) +} + +fn start_receive( + local_path: Option, + remote_path: FilePath, + config: ClientCliConfig, + max_blocks_in_queue: u16, + create_writer: CreateWriter, +) -> BinResult +where + W: Write + Seek, + CreateWriter: Fn(&FilePath) -> BoxedResult, +{ + let socket = create_socket(&config.listen, 1).map_err(|e| BinError::from(e.to_string()))?; + let options = ConnectionOptions { + block_size: config.block_size as u16, + retry_packet_after_timeout: Duration::from_secs(config.retry_timeout), + file_size: Some(0), + encryption_keys: None, + #[cfg(feature = "encryption")] + encryption_level: config + .encryption_level + .parse() + .map_err(|_| BinError::from("Invalid encryption level specified"))?, + + #[cfg(not(feature = "encryption"))] + encryption_level: tftp::encryption::EncryptionLevel::None, + window_size: config.window_size as u16, + }; + #[cfg(feature = "encryption")] + let known_hosts_file = config.known_hosts.clone(); + #[cfg(not(feature = "encryption"))] + let known_hosts_file: Option = None; + let endpoint = config.endpoint.clone(); + + let local_path = match local_path { + Some(p) => p, + None => Path::new(remote_path.as_str()) + .file_name() + .ok_or_else(|| "Invalid remote file name")? + .to_string_lossy() + .parse() + .expect("Invalid remote file name"), + }; + receive_file( + config.try_into(max_blocks_in_queue)?, + local_path, + remote_path, + options, + create_writer, + socket, + instant_callback, + OsRng, + ) + .map(|(total, _remote_key)| { + debug!("Client total received {}", total); + let file = known_hosts_file.as_ref().map(|s| s.as_str()); + handle_hosts_file(file, _remote_key, &endpoint); + total + }) + .map_err(|e| BinError::from(e.to_string())) +} + +fn instant_callback() -> Instant { + #[cfg(feature = "std")] + return std::time::Instant::now(); + #[cfg(not(feature = "std"))] + Instant::from_time(|| { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Time went backwards") + .as_micros() as u64 + }) +} + +#[allow(unused_variables)] +fn handle_hosts_file( + known_hosts_file: Option<&str>, + remote_key: Option, + endpoint: &str, +) { + #[cfg(feature = "encryption")] + match known_hosts_file + .zip(remote_key) + .map(|(f, k)| { + if let Ok(Some(_)) = get_from_known_hosts(create_buff_reader(f)?, endpoint) { + return Ok(()); + } + let file = std::fs::File::options() + .create(true) + .append(true) + .open(f) + .map_err(from_io_err)?; + #[cfg(not(feature = "std"))] + let file = crate::io::StdCompatFile(file); + append_to_known_hosts(file, endpoint, &k) + }) + .transpose() + { + Ok(_) => (), + Err(e) => warn!("Failed to append to known hosts {}", e), + }; +} + +#[cfg(test)] +mod tests { + use std::{ + io::Cursor, + net::UdpSocket, + ops::DerefMut, + sync::{Arc, Mutex}, + thread::{sleep, spawn}, + time::Duration, + }; + + use tftp::{ + client::{receive_file, send_file, ClientConfig}, + config::{ConnectionOptions, MAX_BUFFER_SIZE, MAX_DATA_BLOCK_SIZE}, + encryption::*, + error::{BoxedResult, DefaultBoxedResult}, + server::{server, AuthorizedKeys, ServerConfig}, + std_compat::io, + types::{DefaultString, ExtensionValue, FilePath, ShortString}, + }; + + use super::*; + use crate::cli::ClientCliConfig; + + #[cfg(feature = "encryption")] + #[test] + fn test_client_full_encryption() { + let bytes: Vec = (0..32).map(|_| rand::random::()).collect(); + let key: [u8; 32] = bytes.try_into().unwrap(); + let server_private_key: PrivateKey = key.into(); + client_send( + EncryptionLevel::Protocol, + Some(server_private_key.clone()), + None, + None, + ); + client_receive( + EncryptionLevel::Protocol, + Some(server_private_key), + None, + None, + ); + } + + #[allow(unused_must_use)] + #[cfg(feature = "encryption")] + #[test] + fn test_client_full_encryption_only_authorized() { + // env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init(); + let bytes: Vec = (0..32).map(|_| rand::random::()).collect(); + let key: [u8; 32] = bytes.try_into().unwrap(); + let server_private_key: PrivateKey = key.into(); + let bytes: Vec = (0..32).map(|_| rand::random::()).collect(); + let key: [u8; 32] = bytes.try_into().unwrap(); + let client_private_key: PrivateKey = key.into(); + let mut authorized_keys = AuthorizedKeys::new(); + + authorized_keys.push(PublicKey::from(&client_private_key)); + client_send( + EncryptionLevel::Protocol, + Some(server_private_key.clone()), + #[cfg(feature = "encryption")] + Some(authorized_keys.clone()), + Some(client_private_key.clone()), + ); + client_receive( + EncryptionLevel::Protocol, + Some(server_private_key), + #[cfg(feature = "encryption")] + Some(authorized_keys), + Some(client_private_key), + ); + } + + #[cfg(feature = "encryption")] + #[test] + fn test_client_protocol_encryption() { + client_send(EncryptionLevel::Protocol, None, None, None); + client_receive(EncryptionLevel::Protocol, None, None, None); + } + + #[allow(unused_must_use)] + #[cfg(feature = "encryption")] + #[test] + fn test_client_protocol_encryption_authorized() { + // env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init(); + let bytes: Vec = (0..32).map(|_| rand::random::()).collect(); + let key: [u8; 32] = bytes.try_into().unwrap(); + let client_private_key: PrivateKey = key.into(); + let mut authorized_keys = AuthorizedKeys::new(); + authorized_keys.push(PublicKey::from(&client_private_key)); + client_send( + EncryptionLevel::Protocol, + None, + Some(authorized_keys.clone()), + Some(client_private_key.clone()), + ); + client_receive( + EncryptionLevel::Protocol, + None, + Some(authorized_keys), + Some(client_private_key), + ); + } + + #[cfg(feature = "encryption")] + #[test] + fn test_client_data_encryption() { + // env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init(); + client_send(EncryptionLevel::Data, None, None, None); + client_receive(EncryptionLevel::Data, None, None, None); + } + + #[test] + fn test_client_no_encryption() { + // env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init(); + client_send(EncryptionLevel::None, None, None, None); + client_receive(EncryptionLevel::None, None, None, None); + } + + fn client_send( + encryption_level: EncryptionLevel, + server_private_key: Option, + authorized_keys: Option, + _client_private_key: Option, + ) { + let bytes: Vec = (0..2000).map(|_| rand::random::()).collect(); + let expected_size = bytes.len(); + let expected_data = Arc::new(Mutex::new(Cursor::new(Vec::new()))); + let server_port = get_port(); + #[cfg(feature = "encryption")] + let server_public_key = server_private_key + .as_ref() + .map(|k| encode_public_key(&PublicKey::from(k)).unwrap()); + let _server = { + let d = expected_data.clone(); + spawn(move || { + start_server( + server_port, + Vec::new(), + d, + server_private_key, + authorized_keys, + ) + }) + }; + #[cfg(feature = "encryption")] + let client_private_key = _client_private_key + .as_ref() + .map(|k| encode_private_key(&k).unwrap()); + let client = { + let d = bytes.clone(); + spawn(move || { + sleep(Duration::from_millis(100)); + start_send_file( + server_port, + encryption_level, + d, + #[cfg(feature = "encryption")] + server_public_key, + #[cfg(feature = "encryption")] + client_private_key, + ) + }) + }; + let result = client.join().unwrap(); + assert!(result.is_ok(), "{:?}", result); + assert_eq!(result.unwrap(), expected_size); + assert_eq!(&bytes, expected_data.lock().unwrap().get_ref()); + } + + fn client_receive( + encryption_level: EncryptionLevel, + _server_private_key: Option, + _authorized_keys: Option, + _client_private_key: Option, + ) { + let bytes: Vec = (0..2000).map(|_| rand::random::()).collect(); + let expected_size = bytes.len(); + let expected_data = Arc::new(Mutex::new(Cursor::new(Vec::new()))); + let server_port = get_port(); + #[cfg(feature = "encryption")] + let server_public_key = _server_private_key + .as_ref() + .map(|k| encode_public_key(&PublicKey::from(k)).unwrap()); + let _server = { + let d = bytes.clone(); + spawn(move || { + start_server( + server_port, + d, + Default::default(), + _server_private_key, + _authorized_keys, + ) + }) + }; + + #[cfg(feature = "encryption")] + let client_private_key = _client_private_key + .as_ref() + .map(|k| encode_private_key(&k).unwrap()); + let client = { + let d = expected_data.clone(); + spawn(move || { + sleep(Duration::from_millis(100)); + start_receive_file( + server_port, + encryption_level, + d, + #[cfg(feature = "encryption")] + server_public_key, + #[cfg(feature = "encryption")] + client_private_key, + ) + }) + }; + let result = client.join().unwrap(); + assert!(result.is_ok(), "{:?}", result); + assert_eq!(result.unwrap(), expected_size); + assert_eq!(&bytes, expected_data.lock().unwrap().get_ref()); + } + + fn start_send_file( + server_port: u16, + encryption_level: EncryptionLevel, + bytes: Vec, + #[cfg(feature = "encryption")] server_public_key: Option, + #[cfg(feature = "encryption")] private_key: Option, + ) -> BinResult { + let cli_config = ClientCliConfig { + endpoint: format!("127.0.0.1:{}", server_port).parse().unwrap(), + listen: "127.0.0.1:0".parse().unwrap(), + request_timeout: 1000, + block_size: 100, + retry_timeout: 1, + max_file_size: 2000, + #[cfg(feature = "encryption")] + private_key, + #[cfg(feature = "encryption")] + server_public_key, + #[cfg(feature = "encryption")] + encryption_level: encryption_level.to_string().parse().unwrap(), + #[cfg(feature = "encryption")] + known_hosts: None, + window_size: 1, + allow_server_port_change: false, + }; + + let local_file = "from".parse().unwrap(); + let remote_file = "to".parse().ok(); + let create_reader = + |_path: &FilePath| Ok((Some(bytes.len() as u64), CursorReader::new(bytes.clone()))); + + start_send(local_file, remote_file, cli_config, 4, create_reader) + } + + fn start_receive_file( + server_port: u16, + encryption_level: EncryptionLevel, + bytes: Arc>>>, + #[cfg(feature = "encryption")] server_public_key: Option, + #[cfg(feature = "encryption")] private_key: Option, + ) -> BinResult { + let cli_config = ClientCliConfig { + endpoint: format!("127.0.0.1:{}", server_port).parse().unwrap(), + listen: "127.0.0.1:0".parse().unwrap(), + request_timeout: 1000, + block_size: 100, + retry_timeout: 1, + max_file_size: 2000, + #[cfg(feature = "encryption")] + private_key, + #[cfg(feature = "encryption")] + server_public_key, + #[cfg(feature = "encryption")] + encryption_level: encryption_level.to_string().parse().unwrap(), + #[cfg(feature = "encryption")] + known_hosts: None, + window_size: 1, + allow_server_port_change: false, + }; + + let local_file = "from".parse().ok(); + let remote_file = "to".parse().unwrap(); + let create_writer = |_path: &FilePath| Ok(MutexWriter::new(bytes.clone())); + + start_receive(local_file, remote_file, cli_config, 4, create_writer) + } + + fn start_server( + server_port: u16, + read_bytes: Vec, + write_bytes: Arc>>>, + private_key: Option, + authorized_keys: Option, + ) -> DefaultBoxedResult { + let listen: std::net::SocketAddr = format!("127.0.0.1:{}", server_port).parse().unwrap(); + #[cfg(not(feature = "std"))] + let listen = std_to_socket_addr(listen); + let config = ServerConfig { + listen, + directory: "/tmp".parse().unwrap(), + allow_overwrite: false, + max_queued_blocks_reader: 4, + max_queued_blocks_writer: 4, + request_timeout: Duration::from_millis(100), + max_connections: 10, + max_file_size: 2000, + max_block_size: MAX_DATA_BLOCK_SIZE, + authorized_keys, + private_key, + required_full_encryption: false, + require_server_port_change: false, + max_window_size: 4, + }; + + let create_reader = |_path: &FilePath, _config: &ServerConfig| { + Ok(( + Some(read_bytes.len() as u64), + CursorReader::new(read_bytes.clone()), + )) + }; + let create_writer = + |_path: &FilePath, _config: &ServerConfig| Ok(MutexWriter::new(write_bytes.clone())); + + server( + config, + create_reader, + create_writer, + create_socket, + instant_callback, + OsRng, + ) + } + + struct MutexWriter { + cursor: Arc>>>, + } + + impl MutexWriter { + fn new(cursor: Arc>>>) -> Self { + Self { cursor } + } + } + + impl io::Write for MutexWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + use std::io::Write; + self.cursor.lock().unwrap().write(buf).unwrap(); + Ok(buf.len()) + } + + fn write_fmt( + &mut self, + _: core::fmt::Arguments<'_>, + ) -> Result<(), tftp::std_compat::io::Error> { + todo!() + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + + impl io::Seek for MutexWriter { + fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + use std::io::Seek; + let pos = match pos { + io::SeekFrom::Start(p) => std::io::SeekFrom::Start(p), + io::SeekFrom::Current(p) => std::io::SeekFrom::Current(p), + io::SeekFrom::End(p) => std::io::SeekFrom::End(p), + }; + self.cursor.lock().unwrap().seek(pos).map_err(|_| { + tftp::std_compat::io::Error::from(tftp::std_compat::io::ErrorKind::Other) + }) + } + } + + fn get_port() -> u16 { + let s = UdpSocket::bind("127.0.0.1:0").unwrap(); + s.local_addr().unwrap().port() + } + + #[cfg(feature = "std")] + type CursorReader = Cursor>; + + #[cfg(not(feature = "std"))] + struct CursorReader { + cursor: Cursor>, + } + + #[cfg(not(feature = "std"))] + impl CursorReader { + pub fn new(bytes: Vec) -> Self { + Self { + cursor: Cursor::new(bytes), + } + } + } + + #[cfg(not(feature = "std"))] + impl io::Read for CursorReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + use std::io::Read; + self.cursor + .read(buf) + .map_err(|_| io::Error::from(io::ErrorKind::Other)) + } + } + + #[cfg(not(feature = "std"))] + impl io::Seek for CursorReader { + fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + use std::io::Seek; + let pos = match pos { + io::SeekFrom::Start(p) => std::io::SeekFrom::Start(p), + io::SeekFrom::Current(p) => std::io::SeekFrom::Current(p), + io::SeekFrom::End(p) => std::io::SeekFrom::End(p), + }; + self.cursor.seek(pos).map_err(|_| { + tftp::std_compat::io::Error::from(tftp::std_compat::io::ErrorKind::Other) + }) + } + } +} diff --git a/binary/src/socket.rs b/binary/src/socket.rs new file mode 100644 index 0000000..c560291 --- /dev/null +++ b/binary/src/socket.rs @@ -0,0 +1,183 @@ +use core::time::Duration; + +use log::info; +use polling::{Event, Poller}; +use tftp::{ + config::ConnectionOptions, + encryption::EncryptionLevel, + error::BoxedResult, + socket::*, + std_compat::{io, net::SocketAddr}, + types::DataBuffer, +}; + +use crate::{ + cli::{BinError, BinResult, ClientCliConfig}, + io::from_io_err, +}; + +pub fn create_socket(listen: &str, socket_id: usize) -> BoxedResult { + let socket = std::net::UdpSocket::bind(listen).map_err(from_io_err)?; + socket.set_nonblocking(true).map_err(from_io_err)?; + let local_addr = socket.local_addr().map_err(from_io_err)?; + let poller = if socket_id > 0 { + let poller = Poller::new().map_err(from_io_err)?; + poller + .add(&socket, Event::readable(socket_id)) + .map_err(from_io_err)?; + poller.into() + } else { + None + }; + let socket = StdSocket { + socket, + poller, + socket_id, + }; + Ok(socket) +} + +pub struct StdSocket { + socket: std::net::UdpSocket, + poller: Option, + socket_id: usize, +} + +impl Socket for StdSocket { + fn recv_from( + &self, + buf: &mut DataBuffer, + wait_for: Option, + ) -> io::Result<(usize, SocketAddr)> { + if let (Some(d), Some(poller)) = (wait_for, &self.poller) { + poller + .modify(&self.socket, Event::readable(self.socket_id)) + .map_err(from_io_err)?; + // TODO alloc in stack + let mut events = Vec::new(); + poller.wait(&mut events, d.into()).map_err(from_io_err)?; + } + + #[cfg(feature = "std")] + let result = self.socket.recv_from(buf); + #[cfg(not(feature = "std"))] + let result = self + .socket + .recv_from(buf) + .map(|(b, s)| (b, std_to_socket_addr(s))) + .map_err(from_io_err); + result + } + + fn send_to(&self, buff: &mut DataBuffer, addr: SocketAddr) -> io::Result { + #[cfg(feature = "std")] + return self.socket.send_to(&buff, addr); + #[cfg(not(feature = "std"))] + self.socket + .send_to(&buff, socket_addr_to_std(addr)) + .map_err(from_io_err) + } + + fn try_clone(&self) -> io::Result + where + Self: Sized, + { + Ok(Self { + #[cfg(feature = "std")] + socket: self.socket.try_clone()?, + #[cfg(not(feature = "std"))] + socket: self.socket.try_clone().map_err(from_io_err)?, + poller: None, + socket_id: 0, + }) + } + + fn local_addr(&self) -> io::Result { + #[cfg(feature = "std")] + return self.socket.local_addr(); + #[cfg(not(feature = "std"))] + self.socket + .local_addr() + .map(|s| std_to_socket_addr(s)) + .map_err(from_io_err) + } +} + +#[cfg(not(feature = "std"))] +pub fn std_to_socket_addr(addr: std::net::SocketAddr) -> SocketAddr { + match addr { + std::net::SocketAddr::V4(a) => SocketAddr { + ip: tftp::std_compat::net::IpVersion::Ipv4(a.ip().octets()), + port: a.port(), + }, + std::net::SocketAddr::V6(a) => SocketAddr { + ip: tftp::std_compat::net::IpVersion::Ipv6(a.ip().octets()), + port: a.port(), + }, + } +} + +#[cfg(not(feature = "std"))] +pub fn socket_addr_to_std(addr: SocketAddr) -> std::net::SocketAddr { + match addr.ip { + tftp::std_compat::net::IpVersion::Ipv4(b) => std::net::SocketAddr::V4( + std::net::SocketAddrV4::new(std::net::Ipv4Addr::from(b), addr.port), + ), + tftp::std_compat::net::IpVersion::Ipv6(b) => std::net::SocketAddr::V6( + std::net::SocketAddrV6::new(std::net::Ipv6Addr::from(b), addr.port, 0, 0), + ), + } +} + +#[cfg(test)] +mod tests { + use std::time::Instant; + + use super::*; + + #[test] + fn test_receive_wait_for() { + let socket_r = create_socket("127.0.0.1:9000", 1).unwrap(); + let socket_s = create_socket("127.0.0.1:0", 0).unwrap(); + let mut buf = DataBuffer::new(); + #[allow(unused_must_use)] + { + buf.resize(100, 0); + } + + let now = Instant::now(); + let wait_for = Duration::from_millis(15); + let result = socket_r.recv_from(&mut buf, wait_for.into()); + assert_eq!(result.unwrap_err().kind(), io::ErrorKind::WouldBlock); + assert!(now.elapsed() >= wait_for); + + let now = Instant::now(); + let wait_for = Duration::from_micros(15); + let result = socket_r.recv_from(&mut buf, wait_for.into()); + assert_eq!(result.unwrap_err().kind(), io::ErrorKind::WouldBlock); + assert!(now.elapsed() >= wait_for); + + let now = Instant::now(); + let wait_for = Duration::from_micros(15); + let result = socket_r.recv_from(&mut buf, None); + assert_eq!(result.unwrap_err().kind(), io::ErrorKind::WouldBlock); + assert!(now.elapsed() < wait_for); + + let mut send_buf = DataBuffer::new(); + let addr: std::net::SocketAddr = "127.0.0.1:9000".parse().unwrap(); + #[cfg(not(feature = "std"))] + let addr = std_to_socket_addr(addr); + socket_s.send_to(&mut send_buf, addr).unwrap(); + let now = Instant::now(); + let wait_for = Duration::from_secs(2); + let result = socket_r.recv_from(&mut buf, wait_for.into()); + assert!(result.is_ok()); + assert!(now.elapsed() < wait_for); + + let now = Instant::now(); + let wait_for = Duration::from_micros(15); + let result = socket_r.recv_from(&mut buf, None); + assert_eq!(result.unwrap_err().kind(), io::ErrorKind::WouldBlock); + assert!(now.elapsed() < wait_for); + } +} diff --git a/build b/build new file mode 100755 index 0000000..d9294bd --- /dev/null +++ b/build @@ -0,0 +1,90 @@ +#!/bin/bash + +set -eEux -o pipefail + +TARGETS=(x86_64-unknown-linux-gnu) +RELEASE="release" + +BIN_RELEASE_TARGETS=(x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu armv7-unknown-linux-gnueabihf) +DEB_RELEASE_TARGETS=(x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu armv7-unknown-linux-gnueabihf) +BIN_WINDOWS_TARGETS=(x86_64-pc-windows-gnu) + +build() { + for target in ${TARGETS[@]}; do + cargo build -p tftp-binary --target "$target" "--$RELEASE" + cp target/$target/release/tftp dist/ + cargo build -p tftp-binary --target "$target" "--$RELEASE" --no-default-features --features std + cargo build -p tftp-binary --target "$target" "--$RELEASE" --no-default-features --features alloc + cp target/$target/release/tftp dist/tftp-alloc + cargo build -p tftp-binary --target "$target" "--$RELEASE" --no-default-features --features alloc,encryption + cargo build -p tftp-binary --target "$target" "--$RELEASE" --no-default-features --features std,encryption + cargo build -p tftp-binary --target "$target" "--$RELEASE" --no-default-features --features encryption + cp target/$target/release/tftp dist/tftp-stack-encryption + cargo build -p tftp-binary --target "$target" "--$RELEASE" --no-default-features + cp target/$target/release/tftp dist/tftp-stack + + # just for testing + cargo build -p tftp-binary --target "$target" "--$RELEASE" --features seek + done + + cargo build -p tftp-binary --target "x86_64-unknown-linux-musl" "--$RELEASE" + cp target/x86_64-unknown-linux-musl/release/tftp dist/tftp-static + + build_deb +} + +release_bins() { + for target in ${BIN_RELEASE_TARGETS[@]}; do + + cross build -p tftp-binary --target "$target" --release --no-default-features --features encryption + cp target/$target/release/tftp dist/tftp-stack-$target + # deb depends on this target + cross build -p tftp-binary --target "$target" --release + cp target/$target/release/tftp dist/tftp-$target + done + + for target in ${BIN_WINDOWS_TARGETS[@]}; do + cross build -p tftp-binary --target "$target" --release + cp target/$target/release/tftp.exe dist/tftp-$target.exe + cross build -p tftp-binary --target "$target" --release --no-default-features --features encryption + cp target/$target/release/tftp.exe dist/tftp-stack-$target.exe + done +} + +release_dist() { + rm -f ./dist/* + release_bins + + # cargo build -p tftp-binary --target "x86_64-unknown-linux-musl" "--$RELEASE" + # cp target/x86_64-unknown-linux-musl/release/tftp dist/tftp-static + + release_deb + sign +} + +release_deb() { + for target in ${DEB_RELEASE_TARGETS[@]}; do + cargo deb -p tftp-binary --target $target --no-build --no-strip + cp target/$target/debian/tftp*.deb dist/ + done + # cargo deb -p tftp-binary --target x86_64-unknown-linux-musl + # cp target/x86_64-unknown-linux-musl/debian/tftp_*_amd64.deb dist/ +} + +sign() { + cd dist + + local sum_name="SHA512SUMS" + local sum_path="../target/$sum_name" + + rm -f $sum_name + rm -f $sum_name.sig + > $sum_path + for f in *; do + sha512sum "$f" >> $sum_path + done + cp $sum_path . + gpg --detach-sign --armor -o "$sum_name.sig" $sum_name +} + +$1 diff --git a/builder/debian/postinst b/builder/debian/postinst new file mode 100644 index 0000000..c09cb34 --- /dev/null +++ b/builder/debian/postinst @@ -0,0 +1,4 @@ +[ -z "$SERVER_HOME" ] && SERVER_HOME=/opt/tftp +[ -z "$SERVER_USER" ] && SERVER_USER=tftp + +adduser --system $SERVER_USER --home $SERVER_HOME diff --git a/builder/debian/service b/builder/debian/service new file mode 100644 index 0000000..b28d906 --- /dev/null +++ b/builder/debian/service @@ -0,0 +1,13 @@ +[Unit] +Description=Tftp server + +[Service] +User=tftp +WorkingDirectory=/opt/tftp +ExecStart=/usr/bin/tftp server 0.0.0.0:69 . --allow-overwrite +AmbientCapabilities=CAP_NET_BIND_SERVICE +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +NoNewPrivileges=true + +[Install] +WantedBy=multi-user.target diff --git a/info/README.md b/info/README.md new file mode 100644 index 0000000..2a5889c --- /dev/null +++ b/info/README.md @@ -0,0 +1,39 @@ + +### Transfer times + +Encryption + +![plot](./sender_window_size_delayed_encryption.png) +![plot](./receiver_window_size_delayed_encryption.png) + +No encryption + +![plot](./sender_window_size_no_encryption_stack.png) +![plot](./receiver_window_size_no_encryption_stack.png) + +### Packets dumps + +[Send data](./send_capture_no_encryption_stack.pcap) + +[Receive data](./receive_capture_no_encryption_stack.pcap) + +[Optional encryption send](./send_capture_delayed_encryption.pcap) + +[Optional encryption receive](./receive_capture_delayed_encryption.pcap) + +[Full encryption send and receive](./full_encryption_capture.pcap) + + +### Flamegraphs + +Alloc encryption + +![plot](./send_flamegraph.svg) +![plot](./receive_flamegraph.svg) +![plot](./server_flamegraph.svg) + +Stack no encryption + +![plot](./send_flamegraph_no_encryption_stack.svg) +![plot](./receive_flamegraph_no_encryption_stack.svg) +![plot](./server_flamegraph_no_encryption_stack.svg) \ No newline at end of file diff --git a/info/full_encryption_capture.pcap b/info/full_encryption_capture.pcap new file mode 100644 index 0000000..359a22d Binary files /dev/null and b/info/full_encryption_capture.pcap differ diff --git a/info/receive_capture_delayed_encryption.pcap b/info/receive_capture_delayed_encryption.pcap new file mode 100644 index 0000000..afb394d Binary files /dev/null and b/info/receive_capture_delayed_encryption.pcap differ diff --git a/info/receive_capture_no_encryption_stack.pcap b/info/receive_capture_no_encryption_stack.pcap new file mode 100644 index 0000000..2ebba5a Binary files /dev/null and b/info/receive_capture_no_encryption_stack.pcap differ diff --git a/info/receive_flamegraph.svg b/info/receive_flamegraph.svg new file mode 100644 index 0000000..416dee1 --- /dev/null +++ b/info/receive_flamegraph.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [ld-linux-x86-64.so.2] (2 samples, 0.09%)[ld-linux-x86-64.so.2] (2 samples, 0.09%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (7 samples, 0.31%)[unknown] (1 samples, 0.04%)<tftp::cli::Commands as clap::derive::Subcommand>::augment_subcommands (1 samples, 0.04%)clap::builder::command::Command::new (1 samples, 0.04%)clap::builder::command::Command::new::new_inner (1 samples, 0.04%)<clap::builder::command::Command as core::default::Default>::default (1 samples, 0.04%)<clap::util::flat_map::FlatMap<K,V> as core::default::Default>::default (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.09%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (4 samples, 0.18%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (4 samples, 0.18%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (4 samples, 0.18%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (3 samples, 0.13%)universal_hash::UniversalHash::update_padded (2 samples, 0.09%)universal_hash::to_blocks (2 samples, 0.09%)core::slice::<impl [T]>::split_at (2 samples, 0.09%)core::slice::<impl [T]>::split_at_unchecked (2 samples, 0.09%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (10 samples, 0.45%)tftp::encryption::Encryptor::decrypt (10 samples, 0.45%)aead::AeadInPlace::decrypt_in_place (10 samples, 0.45%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (10 samples, 0.45%)chacha20poly1305::cipher::Cipher<C>::new (3 samples, 0.13%)memcpy (1 samples, 0.04%)[libc.so.6] (11 samples, 0.49%)main (11 samples, 0.49%)std::rt::lang_start (11 samples, 0.49%)std::rt::lang_start_internal (11 samples, 0.49%)std::panic::catch_unwind (11 samples, 0.49%)std::panicking::try (11 samples, 0.49%)std::panicking::try::do_call (11 samples, 0.49%)std::rt::lang_start_internal::{{closure}} (11 samples, 0.49%)std::panic::catch_unwind (11 samples, 0.49%)std::panicking::try (11 samples, 0.49%)std::panicking::try::do_call (11 samples, 0.49%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (11 samples, 0.49%)std::rt::lang_start::{{closure}} (11 samples, 0.49%)std::sys_common::backtrace::__rust_begin_short_backtrace (11 samples, 0.49%)core::ops::function::FnOnce::call_once (11 samples, 0.49%)tftp::main (11 samples, 0.49%)tftp::start_receive (11 samples, 0.49%)tftp::client::client::receive_file (11 samples, 0.49%)tftp::client::client::write_block (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.04%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.04%)core::iter::traits::iterator::Iterator::collect (1 samples, 0.04%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (1 samples, 0.04%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (1 samples, 0.04%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (1 samples, 0.04%)alloc::vec::Vec<T>::with_capacity (1 samples, 0.04%)alloc::vec::Vec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::allocate_in (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.04%)alloc::alloc::Global::alloc_impl (1 samples, 0.04%)clap::parser::parser::Parser::get_matches_with (1 samples, 0.04%)clap::parser::parser::Parser::parse_subcommand (1 samples, 0.04%)clap::builder::command::Command::_build_subcommand (1 samples, 0.04%)clap::builder::command::Command::_build_self (1 samples, 0.04%)clap::builder::debug_asserts::assert_app (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::any (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.04%)core::ops::function::FnOnce::call_once (1 samples, 0.04%)tftp::main (1 samples, 0.04%)tftp::start_receive (1 samples, 0.04%)tftp::client::client::receive_file (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (1 samples, 0.04%)tftp::encryption::Encryptor::decrypt (1 samples, 0.04%)aead::AeadInPlace::decrypt_in_place (1 samples, 0.04%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::new (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)std::rt::lang_start (2 samples, 0.09%)std::rt::lang_start_internal (2 samples, 0.09%)std::panic::catch_unwind (2 samples, 0.09%)std::panicking::try (2 samples, 0.09%)std::panicking::try::do_call (2 samples, 0.09%)std::rt::lang_start_internal::{{closure}} (2 samples, 0.09%)std::panic::catch_unwind (2 samples, 0.09%)std::panicking::try (2 samples, 0.09%)std::panicking::try::do_call (2 samples, 0.09%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (2 samples, 0.09%)std::rt::lang_start::{{closure}} (2 samples, 0.09%)std::sys_common::backtrace::__rust_begin_short_backtrace (2 samples, 0.09%)core::ops::function::FnOnce::call_once (2 samples, 0.09%)tftp::main (2 samples, 0.09%)tftp::start_receive (2 samples, 0.09%)tftp::client::client::receive_file (2 samples, 0.09%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (2 samples, 0.09%)tftp::encryption::Encryptor::decrypt (2 samples, 0.09%)aead::AeadInPlace::decrypt_in_place (2 samples, 0.09%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (2 samples, 0.09%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (2 samples, 0.09%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (2 samples, 0.09%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (2 samples, 0.09%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.04%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.04%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.04%)core::slice::<impl [T]>::chunks_exact (1 samples, 0.04%)core::slice::iter::ChunksExact<T>::new (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (3 samples, 0.13%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (3 samples, 0.13%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (3 samples, 0.13%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (5 samples, 0.22%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (5 samples, 0.22%)core::iter::traits::iterator::Iterator::fold (5 samples, 0.22%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.09%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (6 samples, 0.27%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (6 samples, 0.27%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (6 samples, 0.27%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (6 samples, 0.27%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (6 samples, 0.27%)core::iter::traits::iterator::Iterator::for_each (6 samples, 0.27%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (6 samples, 0.27%)core::iter::traits::iterator::Iterator::fold (6 samples, 0.27%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.13%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)universal_hash::UniversalHash::update_padded (15 samples, 0.67%)universal_hash::UniversalHash::update (9 samples, 0.40%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (9 samples, 0.40%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (9 samples, 0.40%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (9 samples, 0.40%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (24 samples, 1.08%)universal_hash::UniversalHash::verify (3 samples, 0.13%)<[T] as subtle::ConstantTimeEq>::ct_eq (3 samples, 0.13%)<u8 as subtle::ConstantTimeEq>::ct_eq (3 samples, 0.13%)<T as core::convert::Into<U>>::into (3 samples, 0.13%)<subtle::Choice as core::convert::From<u8>>::from (2 samples, 0.09%)subtle::black_box (1 samples, 0.04%)core::ptr::read_volatile (1 samples, 0.04%)zeroize::atomic_fence (2 samples, 0.09%)core::sync::atomic::compiler_fence (1 samples, 0.04%)<[Z] as zeroize::Zeroize>::zeroize (4 samples, 0.18%)zeroize::volatile_set (2 samples, 0.09%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)cipher::stream::StreamCipherSeek::seek (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipherSeek>::try_seek (1 samples, 0.04%)<u64 as cipher::stream::SeekNum>::into_block_byte (1 samples, 0.04%)generic_array::GenericArray<T,N>::from_slice (2 samples, 0.09%)<T as core::convert::Into<U>>::into (2 samples, 0.09%)<&generic_array::GenericArray<T,N> as core::convert::From<&[T]>>::from (2 samples, 0.09%)std::rt::lang_start_internal (37 samples, 1.66%)std::panic::catch_unwind (37 samples, 1.66%)std::panicking::try (37 samples, 1.66%)std::panicking::try::do_call (37 samples, 1.66%)std::rt::lang_start_internal::{{closure}} (37 samples, 1.66%)std::panic::catch_unwind (37 samples, 1.66%)std::panicking::try (37 samples, 1.66%)std::panicking::try::do_call (37 samples, 1.66%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (37 samples, 1.66%)std::rt::lang_start::{{closure}} (37 samples, 1.66%)std::sys_common::backtrace::__rust_begin_short_backtrace (37 samples, 1.66%)core::ops::function::FnOnce::call_once (37 samples, 1.66%)tftp::main (37 samples, 1.66%)tftp::start_receive (37 samples, 1.66%)tftp::client::client::receive_file (37 samples, 1.66%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (37 samples, 1.66%)tftp::encryption::Encryptor::decrypt (37 samples, 1.66%)aead::AeadInPlace::decrypt_in_place (37 samples, 1.66%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (37 samples, 1.66%)chacha20poly1305::cipher::Cipher<C>::new (10 samples, 0.45%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.13%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.13%)universal_hash::UniversalHash::update_padded (1 samples, 0.04%)universal_hash::UniversalHash::update (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)poly1305::backend::autodetect::avx2_cpuid::InitToken::get (1 samples, 0.04%)core::sync::atomic::AtomicU8::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (2 samples, 0.09%)universal_hash::UniversalHash::verify (1 samples, 0.04%)<[T] as subtle::ConstantTimeEq>::ct_eq (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.04%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.04%)std::sys_common::backtrace::__rust_begin_short_backtrace (3 samples, 0.13%)core::ops::function::FnOnce::call_once (3 samples, 0.13%)tftp::main (3 samples, 0.13%)tftp::start_receive (3 samples, 0.13%)tftp::client::client::receive_file (3 samples, 0.13%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (3 samples, 0.13%)tftp::encryption::Encryptor::decrypt (3 samples, 0.13%)aead::AeadInPlace::decrypt_in_place (3 samples, 0.13%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (3 samples, 0.13%)chacha20poly1305::cipher::Cipher<C>::new (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (61 samples, 2.74%)co..core::core_arch::x86::m128iExt::as_i32x4 (10 samples, 0.45%)core::core_arch::x86::sse2::_mm_slli_epi32 (66 samples, 2.97%)cor..core::core_arch::x86::m128iExt::as_i32x4 (21 samples, 0.94%)core::core_arch::x86::sse2::_mm_srli_epi32 (14 samples, 0.63%)core::core_arch::x86::m128iExt::as_i32x4 (7 samples, 0.31%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (360 samples, 16.18%)<tftp::socket::Encryption..tftp::encryption::Encryptor::decrypt (360 samples, 16.18%)tftp::encryption::Encrypt..aead::AeadInPlace::decrypt_in_place (360 samples, 16.18%)aead::AeadInPlace::decryp..<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (360 samples, 16.18%)<chacha20poly1305::ChaCha..chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (360 samples, 16.18%)chacha20poly1305::cipher:..cipher::stream::StreamCipher::apply_keystream (360 samples, 16.18%)cipher::stream::StreamCip..cipher::stream::StreamCipher::try_apply_keystream (360 samples, 16.18%)cipher::stream::StreamCip..<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (360 samples, 16.18%)<cipher::stream_wrapper::..cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (360 samples, 16.18%)cipher::stream_core::Stre..<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (360 samples, 16.18%)<chacha20::xchacha::XChaC..<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (360 samples, 16.18%)<chacha20::ChaChaCore<R> ..chacha20::backends::sse2::inner (360 samples, 16.18%)chacha20::backends::sse2:..<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (360 samples, 16.18%)<cipher::stream_core::App..<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (360 samples, 16.18%)<chacha20::backends::sse2..chacha20::backends::sse2::rounds (360 samples, 16.18%)chacha20::backends::sse2:..chacha20::backends::sse2::double_quarter_round (360 samples, 16.18%)chacha20::backends::sse2:..chacha20::backends::sse2::add_xor_rot (360 samples, 16.18%)chacha20::backends::sse2:..core::core_arch::x86::sse2::_mm_xor_si128 (50 samples, 2.25%)c..<poly1305::Poly1305 as crypto_common::KeyInit>::new (1 samples, 0.04%)poly1305::backend::autodetect::State::new (1 samples, 0.04%)poly1305::backend::soft::State::new (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)tftp::client::client::receive_file (364 samples, 16.36%)tftp::client::client::rec..tftp::client::client::write_block (4 samples, 0.18%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (4 samples, 0.18%)tftp::encryption::Encryptor::encrypt (4 samples, 0.18%)aead::AeadInPlace::encrypt_in_place (4 samples, 0.18%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (4 samples, 0.18%)chacha20poly1305::cipher::Cipher<C>::new (4 samples, 0.18%)cipher::stream::StreamCipher::apply_keystream (3 samples, 0.13%)cipher::stream::StreamCipher::try_apply_keystream (3 samples, 0.13%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (3 samples, 0.13%)cipher::stream_core::StreamCipherCore::write_keystream_block (3 samples, 0.13%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.13%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.13%)chacha20::backends::sse2::inner (3 samples, 0.13%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (3 samples, 0.13%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (3 samples, 0.13%)chacha20::backends::sse2::rounds (3 samples, 0.13%)chacha20::backends::sse2::double_quarter_round (3 samples, 0.13%)chacha20::backends::sse2::rows_to_cols (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.04%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.04%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.18%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (4 samples, 0.18%)<core::slice::iter::ChunksExactMut<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (2 samples, 0.09%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::num::<impl u32>::rotate_left (5 samples, 0.22%)chacha20::xchacha::quarter_round (31 samples, 1.39%)core::num::<impl u32>::wrapping_add (1 samples, 0.04%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (1 samples, 0.04%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)[libc.so.6] (2 samples, 0.09%)core::iter::traits::iterator::Iterator::zip (5 samples, 0.22%)core::iter::adapters::zip::Zip<A,B>::new (5 samples, 0.22%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (3 samples, 0.13%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.04%)<core::slice::iter::ChunksExactMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)core::num::<impl u32>::from_le_bytes (6 samples, 0.27%)core::num::<impl u32>::from_ne_bytes (3 samples, 0.13%)core::result::Result<T,E>::unwrap (1 samples, 0.04%)core::slice::<impl [T]>::chunks_exact (1 samples, 0.04%)core::slice::iter::ChunksExact<T>::new (1 samples, 0.04%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (9 samples, 0.40%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (8 samples, 0.36%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (6 samples, 0.27%)core::ptr::write (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (15 samples, 0.67%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (15 samples, 0.67%)core::iter::traits::iterator::Iterator::fold (14 samples, 0.63%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.22%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::iter_position (2 samples, 0.09%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (19 samples, 0.85%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (19 samples, 0.85%)generic_array::ArrayBuilder<T,N>::new (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (80 samples, 3.60%)<cip..<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (80 samples, 3.60%)<cha..chacha20::xchacha::hchacha (79 samples, 3.55%)chac..memcpy (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (2 samples, 0.09%)universal_hash::UniversalHash::update (2 samples, 0.09%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (2 samples, 0.09%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (2 samples, 0.09%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (2 samples, 0.09%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (2 samples, 0.09%)poly1305::backend::soft::State::compute_block (2 samples, 0.09%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (4 samples, 0.18%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (4 samples, 0.18%)chacha20::backends::sse2::rounds (3 samples, 0.13%)chacha20::backends::sse2::double_quarter_round (2 samples, 0.09%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (5 samples, 0.22%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.22%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.22%)chacha20::backends::sse2::inner (5 samples, 0.22%)core::core_arch::x86::sse2::_mm_loadu_si128 (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.22%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.18%)core::mem::replace (2 samples, 0.09%)core::ptr::read (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (14 samples, 0.63%)cipher::stream::StreamCipher::try_apply_keystream (14 samples, 0.63%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (14 samples, 0.63%)inout::inout_buf::InOutBuf<u8>::xor_in2out (9 samples, 0.40%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::is_null (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.18%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (16 samples, 0.72%)<T as core::convert::TryInto<U>>::try_into (114 samples, 5.12%)<T as ..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (96 samples, 4.31%)core:..core::result::Result<T,E>::map (55 samples, 2.47%)co..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (13 samples, 0.58%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (7 samples, 0.31%)core::slice::raw::from_raw_parts (7 samples, 0.31%)core::ptr::slice_from_raw_parts (3 samples, 0.13%)core::ptr::metadata::from_raw_parts (3 samples, 0.13%)core::convert::num::<impl core::convert::From<u32> for u64>::from (4 samples, 0.18%)core::num::<impl u32>::from_le_bytes (20 samples, 0.90%)core::num::<impl u32>::from_ne_bytes (10 samples, 0.45%)core::result::Result<T,E>::unwrap (42 samples, 1.89%)c..core::ptr::const_ptr::<impl *const T>::add (3 samples, 0.13%)core::ptr::const_ptr::<impl *const T>::offset (3 samples, 0.13%)core::ptr::const_ptr::<impl *const [T]>::as_ptr (2 samples, 0.09%)core::ptr::const_ptr::<impl *const T>::cast (3 samples, 0.13%)universal_hash::UniversalHash::update_padded (327 samples, 14.70%)universal_hash::Univer..universal_hash::UniversalHash::update (327 samples, 14.70%)universal_hash::Univer..<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (327 samples, 14.70%)<poly1305::Poly1305 as..<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (327 samples, 14.70%)<poly1305::backend::au..<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (327 samples, 14.70%)<universal_hash::Unive..<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (323 samples, 14.52%)<poly1305::backend::so..poly1305::backend::soft::State::compute_block (323 samples, 14.52%)poly1305::backend::sof..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (42 samples, 1.89%)c..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (36 samples, 1.62%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (27 samples, 1.21%)core::ptr::slice_from_raw_parts (13 samples, 0.58%)core::ptr::metadata::from_raw_parts (9 samples, 0.40%)poly1305::backend::autodetect::avx2_cpuid::InitToken::get (1 samples, 0.04%)core::sync::atomic::AtomicU8::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)core::slice::<impl [T]>::copy_from_slice (2 samples, 0.09%)core::intrinsics::copy_nonoverlapping (1 samples, 0.04%)memcpy (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.04%)<u8 as core::default::Default>::default (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.09%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.09%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (352 samples, 15.82%)chacha20poly1305::cipher..universal_hash::UniversalHash::verify (9 samples, 0.40%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (9 samples, 0.40%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (9 samples, 0.40%)poly1305::backend::soft::State::finalize_mut (8 samples, 0.36%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.18%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.18%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (1 samples, 0.04%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.04%)core::result::Result<T,E>::ok (1 samples, 0.04%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::get_pos (1 samples, 0.04%)inout::inout_buf::InOutBuf<T>::into_chunks (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (8 samples, 0.36%)cipher::stream::StreamCipher::try_apply_keystream (8 samples, 0.36%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (8 samples, 0.36%)inout::inout_buf::InOutBuf<u8>::xor_in2out (4 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (443 samples, 19.91%)<tftp::socket::EncryptionBoundS..tftp::encryption::Encryptor::decrypt (443 samples, 19.91%)tftp::encryption::Encryptor::de..aead::AeadInPlace::decrypt_in_place (443 samples, 19.91%)aead::AeadInPlace::decrypt_in_p..<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (443 samples, 19.91%)<chacha20poly1305::ChaChaPoly13..chacha20poly1305::cipher::Cipher<C>::new (11 samples, 0.49%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.13%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.13%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.13%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)tftp::client::client::configure_socket (1 samples, 0.04%)tftp::encryption::InitialKeys::finalize (1 samples, 0.04%)x25519_dalek::x25519::EphemeralSecret::diffie_hellman (1 samples, 0.04%)curve25519_dalek::montgomery::<impl core::ops::arith::Mul<curve25519_dalek::montgomery::MontgomeryPoint> for curve25519_dalek::scalar::Scalar>::mul (1 samples, 0.04%)curve25519_dalek::montgomery::<impl core::ops::arith::Mul<&curve25519_dalek::montgomery::MontgomeryPoint> for &curve25519_dalek::scalar::Scalar>::mul (1 samples, 0.04%)<&curve25519_dalek::montgomery::MontgomeryPoint as core::ops::arith::Mul<&curve25519_dalek::scalar::Scalar>>::mul (1 samples, 0.04%)curve25519_dalek::montgomery::differential_add_and_double (1 samples, 0.04%)<&curve25519_dalek::backend::serial::u64::field::FieldElement51 as core::ops::arith::Mul<&curve25519_dalek::backend::serial::u64::field::FieldElement51>>::mul (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)tftp::client::client::query_server (1 samples, 0.04%)tftp::client::client::wait_for_initial_packet (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (3 samples, 0.13%)core::iter::traits::iterator::Iterator::collect (3 samples, 0.13%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (3 samples, 0.13%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (3 samples, 0.13%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (3 samples, 0.13%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (3 samples, 0.13%)alloc::vec::Vec<T,A>::extend_trusted (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.04%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (2 samples, 0.09%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)memcpy (1 samples, 0.04%)chacha20::xchacha::quarter_round (2 samples, 0.09%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (6 samples, 0.27%)chacha20::xchacha::hchacha (4 samples, 0.18%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)core::ptr::write (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (9 samples, 0.40%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.13%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.13%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.09%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (4 samples, 0.18%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (4 samples, 0.18%)poly1305::backend::soft::State::finalize_mut (4 samples, 0.18%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.18%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.18%)core::iter::traits::iterator::Iterator::for_each (4 samples, 0.18%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.18%)core::iter::traits::iterator::Iterator::fold (4 samples, 0.18%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (1 samples, 0.04%)universal_hash::UniversalHash::update (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.04%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.04%)poly1305::backend::soft::State::compute_block (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (6 samples, 0.27%)universal_hash::UniversalHash::update_padded (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)tftp::main (465 samples, 20.90%)tftp::maintftp::start_receive (465 samples, 20.90%)tftp::start_receivetftp::client::client::receive_file (465 samples, 20.90%)tftp::client::client::receive_filetftp::client::client::write_block (20 samples, 0.90%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (17 samples, 0.76%)tftp::encryption::Encryptor::encrypt (17 samples, 0.76%)aead::AeadInPlace::encrypt_in_place (17 samples, 0.76%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (17 samples, 0.76%)chacha20poly1305::cipher::Cipher<C>::new (2 samples, 0.09%)cipher::stream::StreamCipher::apply_keystream (2 samples, 0.09%)cipher::stream::StreamCipher::try_apply_keystream (2 samples, 0.09%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (2 samples, 0.09%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)chacha20::backends::sse2::cols_to_rows (19 samples, 0.85%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (13 samples, 0.58%)core::core_arch::x86::m128iExt::as_i32x4 (3 samples, 0.13%)chacha20::backends::sse2::double_quarter_round (51 samples, 2.29%)c..chacha20::backends::sse2::rows_to_cols (28 samples, 1.26%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (20 samples, 0.90%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (6 samples, 0.27%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.09%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)core::clone::impls::<impl core::clone::Clone for usize>::clone (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (4 samples, 0.18%)chacha20::backends::sse2::rounds (91 samples, 4.09%)chac..core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (18 samples, 0.81%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (16 samples, 0.72%)core::mem::replace (4 samples, 0.18%)core::ptr::read (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_set_epi32 (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_storeu_si128 (3 samples, 0.13%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.09%)core::ptr::read (2 samples, 0.09%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.22%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.22%)core::mem::replace (3 samples, 0.13%)core::ptr::write (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (107 samples, 4.81%)<chach..core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)<inout::inout_buf::InOutBufIter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::ptr::write (18 samples, 0.81%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (149 samples, 6.70%)<core::it..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (99 samples, 4.45%)core:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (73 samples, 3.28%)<ge..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (9 samples, 0.40%)<u8 as core::default::Default>::default (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (21 samples, 0.94%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (10 samples, 0.45%)core::ptr::mut_ptr::<impl *mut T>::addr (8 samples, 0.36%)core::ptr::mut_ptr::<impl *mut T>::add (8 samples, 0.36%)core::ptr::mut_ptr::<impl *mut T>::offset (7 samples, 0.31%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (319 samples, 14.34%)core::iter::traits::it..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (316 samples, 14.20%)<core::iter::adapters:..core::iter::traits::iterator::Iterator::fold (315 samples, 14.16%)core::iter::traits::i..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (89 samples, 4.00%)<cor..core::slice::iter::IterMut<T>::post_inc_start (45 samples, 2.02%)c..core::ptr::non_null::NonNull<T>::new_unchecked (5 samples, 0.22%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (5 samples, 0.22%)core::ptr::read (1 samples, 0.04%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)_init (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (329 samples, 14.79%)generic_array::impls::<..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (329 samples, 14.79%)<generic_array::Generic..generic_array::ArrayBuilder<T,N>::iter_position (3 samples, 0.13%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::cast (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (72 samples, 3.24%)<ge..core::slice::raw::from_raw_parts (55 samples, 2.47%)co..core::ptr::slice_from_raw_parts (44 samples, 1.98%)c..core::ptr::metadata::from_raw_parts (39 samples, 1.75%)core::ptr::metadata::from_raw_parts_mut (11 samples, 0.49%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (29 samples, 1.30%)core::slice::raw::from_raw_parts_mut (22 samples, 0.99%)core::ptr::slice_from_raw_parts_mut (17 samples, 0.76%)core::ptr::mut_ptr::<impl *mut T>::cast (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (17 samples, 0.76%)core::clone::impls::<impl core::clone::Clone for usize>::clone (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (9 samples, 0.40%)core::ptr::read (29 samples, 1.30%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.09%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (2 samples, 0.09%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (105 samples, 4.72%)core:..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (99 samples, 4.45%)<core..core::mem::replace (43 samples, 1.93%)c..core::ptr::write (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::ptr::read (2 samples, 0.09%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::ptr::write (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::ptr::write (9 samples, 0.40%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (157 samples, 7.06%)<core::it..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (103 samples, 4.63%)core:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (77 samples, 3.46%)<ge..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (14 samples, 0.63%)<u8 as core::default::Default>::default (2 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (11 samples, 0.49%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (4 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::addr (3 samples, 0.13%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (12 samples, 0.54%)core::ptr::mut_ptr::<impl *mut T>::offset (12 samples, 0.54%)core::iter::traits::iterator::Iterator::for_each (302 samples, 13.57%)core::iter::traits::i..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (300 samples, 13.48%)<core::iter::adapter..core::iter::traits::iterator::Iterator::fold (300 samples, 13.48%)core::iter::traits::..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (71 samples, 3.19%)<co..core::slice::iter::IterMut<T>::post_inc_start (40 samples, 1.80%)c..core::ptr::non_null::NonNull<T>::new_unchecked (2 samples, 0.09%)[libc.so.6] (2 samples, 0.09%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.13%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (7 samples, 0.31%)core::ptr::read (3 samples, 0.13%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (3 samples, 0.13%)core::slice::raw::from_raw_parts_mut (3 samples, 0.13%)core::ptr::slice_from_raw_parts_mut (2 samples, 0.09%)core::ptr::metadata::from_raw_parts_mut (2 samples, 0.09%)generic_array::ArrayBuilder<T,N>::iter_position (5 samples, 0.22%)core::slice::<impl [T]>::iter_mut (2 samples, 0.09%)core::slice::iter::IterMut<T>::new (2 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (1,110 samples, 49.89%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,110 samples, 49.89%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::proc..<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,110 samples, 49.89%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_b..chacha20::backends::sse2::inner (1,110 samples, 49.89%)chacha20::backends::sse2::inner<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (1,110 samples, 49.89%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::c..inout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (672 samples, 30.20%)inout::inout::InOut<generic_array::GenericArray<u..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (315 samples, 14.16%)generic_array::impls:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (315 samples, 14.16%)<generic_array::Gener..generic_array::ArrayBuilder<T,N>::new (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (9 samples, 0.40%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_slli_epi32 (3 samples, 0.13%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)chacha20::backends::sse2::add_xor_rot (21 samples, 0.94%)core::core_arch::x86::sse2::_mm_xor_si128 (5 samples, 0.22%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (1,133 samples, 50.92%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detachedcipher::stream::StreamCipher::apply_keystream (1,133 samples, 50.92%)cipher::stream::StreamCipher::apply_keystreamcipher::stream::StreamCipher::try_apply_keystream (1,133 samples, 50.92%)cipher::stream::StreamCipher::try_apply_keystream<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1,133 samples, 50.92%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>..cipher::stream_core::StreamCipherCore::write_keystream_block (23 samples, 1.03%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (23 samples, 1.03%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (23 samples, 1.03%)chacha20::backends::sse2::inner (23 samples, 1.03%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (23 samples, 1.03%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (23 samples, 1.03%)chacha20::backends::sse2::rounds (23 samples, 1.03%)chacha20::backends::sse2::double_quarter_round (23 samples, 1.03%)chacha20::backends::sse2::rows_to_cols (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (2 samples, 0.09%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.13%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.09%)core::result::Result<T,E>::map (2 samples, 0.09%)core::num::<impl u32>::from_le_bytes (1 samples, 0.04%)core::num::<impl u32>::from_ne_bytes (1 samples, 0.04%)core::result::Result<T,E>::unwrap (1 samples, 0.04%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (7 samples, 0.31%)poly1305::backend::autodetect::State::new (7 samples, 0.31%)poly1305::backend::soft::State::new (6 samples, 0.27%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (2 samples, 0.09%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.09%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.09%)chacha20::backends::sse2::inner (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_loadu_si128 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (3 samples, 0.13%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_slli_epi32 (3 samples, 0.13%)chacha20::backends::sse2::add_xor_rot (16 samples, 0.72%)core::core_arch::x86::sse2::_mm_xor_si128 (2 samples, 0.09%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (19 samples, 0.85%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.04%)chacha20::backends::sse2::rounds (21 samples, 0.94%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (1,168 samples, 52.49%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_fromtftp::encryption::Encryptor::decrypt (1,168 samples, 52.49%)tftp::encryption::Encryptor::decryptaead::AeadInPlace::decrypt_in_place (1,168 samples, 52.49%)aead::AeadInPlace::decrypt_in_place<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (1,168 samples, 52.49%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detachedchacha20poly1305::cipher::Cipher<C>::new (35 samples, 1.57%)cipher::stream::StreamCipher::apply_keystream (28 samples, 1.26%)cipher::stream::StreamCipher::try_apply_keystream (28 samples, 1.26%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (28 samples, 1.26%)cipher::stream_core::StreamCipherCore::write_keystream_block (26 samples, 1.17%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (26 samples, 1.17%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (26 samples, 1.17%)chacha20::backends::sse2::inner (26 samples, 1.17%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (23 samples, 1.03%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (23 samples, 1.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)core::mem::replace (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1 samples, 0.04%)cipher::stream::StreamCipher::try_apply_keystream (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)chacha20::backends::sse2::inner (1 samples, 0.04%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (1 samples, 0.04%)chacha20::backends::sse2::rounds (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (1 samples, 0.04%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)[unknown] (2,055 samples, 92.36%)[unknown]tftp::start_receive (1,170 samples, 52.58%)tftp::start_receivetftp::client::client::receive_file (1,170 samples, 52.58%)tftp::client::client::receive_filetftp::client::client::write_block (2 samples, 0.09%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (2 samples, 0.09%)tftp::encryption::Encryptor::encrypt (2 samples, 0.09%)aead::AeadInPlace::encrypt_in_place (2 samples, 0.09%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (2 samples, 0.09%)chacha20poly1305::cipher::Cipher<C>::new (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1 samples, 0.04%)cipher::stream::StreamCipher::try_apply_keystream (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)chacha20::backends::sse2::inner (1 samples, 0.04%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (1 samples, 0.04%)chacha20::backends::sse2::rounds (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)env_logger::Builder::init (1 samples, 0.04%)env_logger::Builder::try_init (1 samples, 0.04%)env_logger::Builder::build (1 samples, 0.04%)env_logger::filter::Builder::build (1 samples, 0.04%)std::collections::hash::map::HashMap<K,V,S>::is_empty (1 samples, 0.04%)hashbrown::map::HashMap<K,V,S,A>::is_empty (1 samples, 0.04%)hashbrown::map::HashMap<K,V,S,A>::len (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<core::option::Option<T> as core::convert::From<T>>::from (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)core::option::Option<T>::ok_or (1 samples, 0.04%)core::slice::<impl [T]>::get (1 samples, 0.04%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (4 samples, 0.18%)tftp::packet::try_from (2 samples, 0.09%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)core::slice::<impl [T]>::get (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (7 samples, 0.31%)tftp::packet::PacketType::from_bytes (1 samples, 0.04%)tftp::packet::try_from (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)[libc.so.6] (3 samples, 0.13%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (1 samples, 0.04%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (1 samples, 0.04%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (1 samples, 0.04%)log::max_level (1 samples, 0.04%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)polling::Poller::modify (3 samples, 0.13%)polling::epoll::Poller::modify (3 samples, 0.13%)polling::epoll::Poller::ctl (2 samples, 0.09%)core::option::Option<T>::map (1 samples, 0.04%)polling::epoll::Poller::ctl::{{closure}} (1 samples, 0.04%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (2 samples, 0.09%)core::iter::traits::iterator::Iterator::try_fold (2 samples, 0.09%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.13%)core::iter::traits::iterator::Iterator::find (3 samples, 0.13%)core::ops::control_flow::ControlFlow<B,C>::break_value (1 samples, 0.04%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.09%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.09%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.09%)core::ptr::const_ptr::<impl *const T>::sub_ptr (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (9 samples, 0.40%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (9 samples, 0.40%)alloc::vec::Vec<T,A>::extend_desugared (9 samples, 0.40%)alloc::vec::Vec<T,A>::reserve (4 samples, 0.18%)alloc::raw_vec::RawVec<T,A>::reserve (4 samples, 0.18%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (4 samples, 0.18%)alloc::raw_vec::RawVec<T,A>::grow_amortized (3 samples, 0.13%)alloc::raw_vec::finish_grow (3 samples, 0.13%)core::result::Result<T,E>::map_err (1 samples, 0.04%)<std::sync::mutex::MutexGuard<T> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)polling::epoll::Events::iter (1 samples, 0.04%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.09%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.04%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (2 samples, 0.09%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.09%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (2 samples, 0.09%)core::time::Duration::from_secs (1 samples, 0.04%)core::time::Duration::new (1 samples, 0.04%)core::num::<impl u64>::checked_add (1 samples, 0.04%)epoll_wait (22 samples, 0.99%)log::max_level (1 samples, 0.04%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)polling::epoll::Poller::wait (33 samples, 1.48%)read (1 samples, 0.04%)std::sync::poison::Flag::get (1 samples, 0.04%)core::sync::atomic::AtomicBool::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)std::sync::poison::Flag::guard (2 samples, 0.09%)std::thread::panicking (1 samples, 0.04%)std::panicking::panicking (1 samples, 0.04%)std::panicking::panic_count::count_is_zero (1 samples, 0.04%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (56 samples, 2.52%)<t..polling::Poller::wait (48 samples, 2.16%)p..std::sync::mutex::Mutex<T>::try_lock (4 samples, 0.18%)std::sync::mutex::MutexGuard<T>::new (4 samples, 0.18%)std::sync::poison::map_result (1 samples, 0.04%)alloc::vec::Vec<T,A>::truncate (1 samples, 0.04%)<alloc::vec::Vec<u8> as aead::Buffer>::truncate (1 samples, 0.04%)alloc::vec::Vec<T,A>::truncate (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.09%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.09%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (4 samples, 0.18%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.18%)core::iter::traits::iterator::Iterator::fold (4 samples, 0.18%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.09%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (9 samples, 0.40%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (5 samples, 0.22%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (5 samples, 0.22%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (13 samples, 0.58%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (8 samples, 0.36%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (5 samples, 0.22%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (21 samples, 0.94%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (20 samples, 0.90%)core::iter::traits::iterator::Iterator::fold (20 samples, 0.90%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.13%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (31 samples, 1.39%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (22 samples, 0.99%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (22 samples, 0.99%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.04%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (4 samples, 0.18%)universal_hash::UniversalHash::update (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (7 samples, 0.31%)<[Z] as zeroize::Zeroize>::zeroize (7 samples, 0.31%)zeroize::volatile_set (6 samples, 0.27%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.18%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.13%)core::mem::replace (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)<&mut I as core::iter::traits::iterator::Iterator>::next (2 samples, 0.09%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.09%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (14 samples, 0.63%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (7 samples, 0.31%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (6 samples, 0.27%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (5 samples, 0.22%)<[Z: N] as zeroize::Zeroize>::zeroize (5 samples, 0.22%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (5 samples, 0.22%)<Z as zeroize::Zeroize>::zeroize (1 samples, 0.04%)zeroize::atomic_fence (1 samples, 0.04%)core::sync::atomic::compiler_fence (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::slice::<impl [T]>::split_at (1 samples, 0.04%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (53 samples, 2.38%)<c..chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (22 samples, 0.99%)universal_hash::UniversalHash::update_padded (3 samples, 0.13%)universal_hash::to_blocks (2 samples, 0.09%)core::slice::raw::from_raw_parts (1 samples, 0.04%)<typenum::bit::B0 as typenum::marker_traits::Bit>::to_u8 (2 samples, 0.09%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (5 samples, 0.22%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (2 samples, 0.09%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (2 samples, 0.09%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)<typenum::uint::UTerm as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)aead::Buffer::len (1 samples, 0.04%)core::slice::<impl [T]>::split_at_mut (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (125 samples, 5.62%)<tftp::..tftp::encryption::Encryptor::decrypt (65 samples, 2.92%)tf..aead::AeadInPlace::decrypt_in_place (64 samples, 2.88%)ae..generic_array::GenericArray<T,N>::from_slice (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<alloc::vec::ExtendElement<T> as alloc::vec::ExtendWith<T>>::next (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)alloc::vec::Vec<T,A>::resize (3 samples, 0.13%)alloc::vec::Vec<T,A>::extend_with (3 samples, 0.13%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)alloc::vec::Vec<T,A>::truncate (1 samples, 0.04%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.09%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.04%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.04%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.04%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.04%)core::iter::traits::iterator::Iterator::collect (1 samples, 0.04%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (1 samples, 0.04%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (1 samples, 0.04%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (1 samples, 0.04%)std::net::udp::UdpSocket::send_to (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (2 samples, 0.09%)tftp::encryption::Encryptor::encrypt (1 samples, 0.04%)aead::AeadInPlace::encrypt_in_place (1 samples, 0.04%)<alloc::vec::Vec<u8> as aead::Buffer>::extend_from_slice (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_from_slice (1 samples, 0.04%)core::slice::<impl [T]>::iter (1 samples, 0.04%)core::slice::iter::Iter<T>::new (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::get (1 samples, 0.04%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (1 samples, 0.04%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (5 samples, 0.22%)tftp::storage::BlockMapper::index (1 samples, 0.04%)tftp::client::client::write_block (13 samples, 0.58%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (3 samples, 0.13%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (3 samples, 0.13%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (3 samples, 0.13%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (1 samples, 0.04%)alloc::alloc::dealloc (1 samples, 0.04%)cfree (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)tftp::instant_callback (2 samples, 0.09%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (2 samples, 0.09%)clock_gettime (2 samples, 0.09%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.09%)all (2,225 samples, 100%)tftp (2,225 samples, 100.00%)tftp_start (163 samples, 7.33%)_start__libc_start_main (163 samples, 7.33%)__libc_sta..[libc.so.6] (163 samples, 7.33%)[libc.so.6]main (163 samples, 7.33%)mainstd::rt::lang_start (163 samples, 7.33%)std::rt::l..std::rt::lang_start_internal (163 samples, 7.33%)std::rt::l..std::panic::catch_unwind (163 samples, 7.33%)std::panic..std::panicking::try (163 samples, 7.33%)std::panic..std::panicking::try::do_call (163 samples, 7.33%)std::panic..std::rt::lang_start_internal::{{closure}} (163 samples, 7.33%)std::rt::l..std::panic::catch_unwind (163 samples, 7.33%)std::panic..std::panicking::try (163 samples, 7.33%)std::panic..std::panicking::try::do_call (163 samples, 7.33%)std::panic..core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (163 samples, 7.33%)core::ops:..std::rt::lang_start::{{closure}} (163 samples, 7.33%)std::rt::l..std::sys_common::backtrace::__rust_begin_short_backtrace (163 samples, 7.33%)std::sys_c..core::ops::function::FnOnce::call_once (163 samples, 7.33%)core::ops:..tftp::main (163 samples, 7.33%)tftp::maintftp::start_receive (162 samples, 7.28%)tftp::star..tftp::client::client::receive_file (162 samples, 7.28%)tftp::clie..tftp::packet::PacketType::from_bytes (4 samples, 0.18%)tftp::packet::try_from (4 samples, 0.18%)core::slice::<impl [T]>::get (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%) \ No newline at end of file diff --git a/info/receive_flamegraph_delayed_encryption_stack.svg b/info/receive_flamegraph_delayed_encryption_stack.svg new file mode 100644 index 0000000..b8677ae --- /dev/null +++ b/info/receive_flamegraph_delayed_encryption_stack.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [[stack]] (1 samples, 0.03%)epoll_ctl (1 samples, 0.03%)[unknown] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (6 samples, 0.21%)[unknown] (1 samples, 0.03%)<tftp::cli::Commands as clap::derive::Subcommand>::augment_subcommands (1 samples, 0.03%)clap::builder::arg::Arg::value_name (1 samples, 0.03%)clap::builder::arg::Arg::value_names (1 samples, 0.03%)core::iter::traits::iterator::Iterator::collect (1 samples, 0.03%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (1 samples, 0.03%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (1 samples, 0.03%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (1 samples, 0.03%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.03%)alloc::vec::Vec<T,A>::extend_trusted (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::ptr::drop_in_place<core::array::iter::IntoIter<clap::builder::str::Str,1_usize>> (1 samples, 0.03%)<core::array::iter::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.03%)core::array::iter::IntoIter<T,_>::as_mut_slice (1 samples, 0.03%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.03%)core::iter::traits::iterator::Iterator::collect (1 samples, 0.03%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (1 samples, 0.03%)core::ptr::drop_in_place<core::array::iter::IntoIter<u8,2_usize>> (1 samples, 0.03%)<core::array::iter::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.03%)core::array::iter::IntoIter<T,_>::as_mut_slice (1 samples, 0.03%)core::slice::<impl [T]>::get_unchecked_mut (1 samples, 0.03%)<core::ops::index_range::IndexRange as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (5 samples, 0.17%)core::iter::traits::iterator::Iterator::collect (3 samples, 0.10%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (3 samples, 0.10%)core::ptr::drop_in_place<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,heapless::vec::IntoIter<u8,1420_usize>>> (1 samples, 0.03%)core::ptr::drop_in_place<core::option::Option<heapless::vec::IntoIter<u8,1420_usize>>> (1 samples, 0.03%)__rust_probestack (1 samples, 0.03%)<T as core::convert::Into<U>>::into (1 samples, 0.03%)<core::option::Option<T> as core::convert::From<T>>::from (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (4 samples, 0.14%)heapless::vec::Vec<T,_>::as_slice (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (1 samples, 0.03%)core::slice::<impl [T]>::get (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.03%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (5 samples, 0.17%)tftp::packet::PacketType::from_bytes (3 samples, 0.10%)tftp::packet::try_from (3 samples, 0.10%)core::slice::<impl [T]>::get (1 samples, 0.03%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)alloc::vec::Vec<T>::new (1 samples, 0.03%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (3 samples, 0.10%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (3 samples, 0.10%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (3 samples, 0.10%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (3 samples, 0.10%)alloc::alloc::dealloc (1 samples, 0.03%)cfree (1 samples, 0.03%)std::net::ip_addr::Ipv4Addr::octets (2 samples, 0.07%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from::{{closure}} (4 samples, 0.14%)tftp::socket::std_to_socket_addr (3 samples, 0.10%)std::net::socket_addr::SocketAddrV4::port (1 samples, 0.03%)[libc.so.6] (2 samples, 0.07%)core::result::Result<T,E>::map (7 samples, 0.24%)memcpy (1 samples, 0.03%)<tftp::std_compat::io::Error as core::convert::From<tftp::std_compat::io::ErrorKind>>::from (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.07%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (2 samples, 0.07%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (2 samples, 0.07%)std::io::error::repr_bitpacked::decode_repr (2 samples, 0.07%)core::result::Result<T,E>::map_err (8 samples, 0.28%)core::ops::function::FnOnce::call_once (6 samples, 0.21%)tftp::io::from_io_err (5 samples, 0.17%)std::io::error::Error::kind (2 samples, 0.07%)std::io::error::repr_bitpacked::Repr::data (1 samples, 0.03%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.03%)polling::Event::readable (1 samples, 0.03%)<&T as polling::Source>::raw (2 samples, 0.07%)std::os::fd::net::<impl std::os::fd::raw::AsRawFd for std::net::udp::UdpSocket>::as_raw_fd (1 samples, 0.03%)polling::Poller::modify (3 samples, 0.10%)polling::epoll::Poller::modify (1 samples, 0.03%)polling::epoll::Poller::ctl (1 samples, 0.03%)core::option::Option<T>::map (1 samples, 0.03%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.10%)core::iter::traits::iterator::Iterator::find (3 samples, 0.10%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (3 samples, 0.10%)core::iter::traits::iterator::Iterator::try_fold (3 samples, 0.10%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::is_null (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (2 samples, 0.07%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.07%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.07%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.07%)core::ptr::const_ptr::<impl *const T>::sub_ptr (2 samples, 0.07%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.03%)__rdl_alloc (1 samples, 0.03%)alloc::alloc::alloc (7 samples, 0.24%)malloc (6 samples, 0.21%)alloc::raw_vec::finish_grow (10 samples, 0.35%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (10 samples, 0.35%)alloc::alloc::Global::alloc_impl (10 samples, 0.35%)core::ptr::non_null::NonNull<T>::new (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.03%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (18 samples, 0.62%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (18 samples, 0.62%)alloc::vec::Vec<T,A>::extend_desugared (18 samples, 0.62%)alloc::vec::Vec<T,A>::reserve (13 samples, 0.45%)alloc::raw_vec::RawVec<T,A>::reserve (13 samples, 0.45%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (12 samples, 0.41%)alloc::raw_vec::RawVec<T,A>::grow_amortized (12 samples, 0.41%)core::cmp::max (1 samples, 0.03%)core::cmp::Ord::max (1 samples, 0.03%)core::cmp::max_by (1 samples, 0.03%)core::iter::traits::iterator::Iterator::filter (1 samples, 0.03%)std::sync::poison::Flag::done (1 samples, 0.03%)std::thread::panicking (1 samples, 0.03%)std::panicking::panicking (1 samples, 0.03%)std::panicking::panic_count::count_is_zero (1 samples, 0.03%)core::sync::atomic::AtomicUsize::load (1 samples, 0.03%)core::sync::atomic::atomic_load (1 samples, 0.03%)core::ptr::drop_in_place<std::sync::mutex::MutexGuard<polling::epoll::Events>> (5 samples, 0.17%)<std::sync::mutex::MutexGuard<T> as core::ops::drop::Drop>::drop (4 samples, 0.14%)std::sys::unix::locks::futex_mutex::Mutex::unlock (2 samples, 0.07%)core::sync::atomic::AtomicU32::swap (2 samples, 0.07%)core::sync::atomic::atomic_swap (2 samples, 0.07%)core::sync::atomic::AtomicBool::swap (1 samples, 0.03%)core::sync::atomic::atomic_swap (1 samples, 0.03%)polling::epoll::Events::iter (1 samples, 0.03%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.03%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.03%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.03%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.03%)core::time::Duration::as_secs (1 samples, 0.03%)epoll_wait (18 samples, 0.62%)log::max_level (1 samples, 0.03%)core::sync::atomic::AtomicUsize::load (1 samples, 0.03%)core::sync::atomic::atomic_load (1 samples, 0.03%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)core::option::Option<T>::map (1 samples, 0.03%)polling::epoll::Poller::modify (4 samples, 0.14%)polling::epoll::Poller::ctl (3 samples, 0.10%)core::option::Option<T>::unwrap_or (1 samples, 0.03%)read (1 samples, 0.03%)polling::epoll::Poller::wait (31 samples, 1.07%)std::io::error::Error::last_os_error (1 samples, 0.03%)std::sys::unix::os::errno (1 samples, 0.03%)__errno_location (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.07%)std::sync::mutex::MutexGuard<T>::new (1 samples, 0.03%)std::sync::poison::Flag::guard (1 samples, 0.03%)std::sync::poison::Flag::get (1 samples, 0.03%)core::sync::atomic::AtomicBool::load (1 samples, 0.03%)core::sync::atomic::atomic_load (1 samples, 0.03%)polling::Poller::wait (63 samples, 2.18%)p..std::sync::mutex::Mutex<T>::try_lock (6 samples, 0.21%)std::sys::unix::locks::futex_mutex::Mutex::try_lock (1 samples, 0.03%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (92 samples, 3.18%)<tf..std::net::udp::UdpSocket::recv_from (2 samples, 0.07%)std::sys_common::net::UdpSocket::recv_from (1 samples, 0.03%)std::sys::unix::net::Socket::recv_from (1 samples, 0.03%)std::sys::unix::net::Socket::recv_from_with_flags (1 samples, 0.03%)std::sys::unix::cvt (1 samples, 0.03%)std::io::error::Error::last_os_error (1 samples, 0.03%)std::sys::unix::os::errno (1 samples, 0.03%)__errno_location (1 samples, 0.03%)heapless::vec::Vec<T,_>::truncate (1 samples, 0.03%)log::max_level (1 samples, 0.03%)core::sync::atomic::AtomicUsize::load (1 samples, 0.03%)core::sync::atomic::atomic_load (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (5 samples, 0.17%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (4 samples, 0.14%)core::result::Result<T,E>::map (1 samples, 0.03%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.07%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (2 samples, 0.07%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.03%)chacha20::avx2_cpuid::init (1 samples, 0.03%)chacha20::avx2_cpuid::init_get (1 samples, 0.03%)core::sync::atomic::AtomicU8::load (1 samples, 0.03%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (1 samples, 0.03%)core::result::Result<T,E>::unwrap (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (13 samples, 0.45%)core::slice::<impl [T]>::iter_mut (3 samples, 0.10%)core::slice::iter::IterMut<T>::new (3 samples, 0.10%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.10%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (3 samples, 0.10%)core::result::Result<T,E>::map (2 samples, 0.07%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.03%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (2 samples, 0.07%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.17%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (4 samples, 0.14%)<core::slice::iter::ChunksExactMut<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)[libc.so.6] (2 samples, 0.07%)core::num::<impl u32>::rotate_left (6 samples, 0.21%)chacha20::xchacha::quarter_round (34 samples, 1.17%)core::num::<impl u32>::wrapping_add (4 samples, 0.14%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (2 samples, 0.07%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.07%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.07%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.07%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (2 samples, 0.07%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (2 samples, 0.07%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)core::cmp::min (1 samples, 0.03%)core::cmp::Ord::min (1 samples, 0.03%)core::cmp::min_by (1 samples, 0.03%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (3 samples, 0.10%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::size_hint (3 samples, 0.10%)core::iter::traits::iterator::Iterator::zip (6 samples, 0.21%)core::iter::adapters::zip::Zip<A,B>::new (6 samples, 0.21%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (5 samples, 0.17%)memcpy (1 samples, 0.03%)core::num::<impl u32>::from_le_bytes (2 samples, 0.07%)core::slice::<impl [T]>::chunks_exact (2 samples, 0.07%)core::slice::iter::ChunksExact<T>::new (2 samples, 0.07%)core::slice::<impl [T]>::split_at_unchecked (2 samples, 0.07%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)core::slice::<impl [T]>::copy_from_slice (1 samples, 0.03%)core::intrinsics::copy_nonoverlapping (1 samples, 0.03%)memcpy (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (4 samples, 0.14%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)core::ptr::write (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (7 samples, 0.24%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (4 samples, 0.14%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (3 samples, 0.10%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (13 samples, 0.45%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (13 samples, 0.45%)core::iter::traits::iterator::Iterator::fold (12 samples, 0.41%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)chacha20::xchacha::hchacha (84 samples, 2.90%)ch..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (15 samples, 0.52%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (15 samples, 0.52%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.03%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.10%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (4 samples, 0.14%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.14%)core::iter::traits::iterator::Iterator::fold (4 samples, 0.14%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (105 samples, 3.63%)<cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (6 samples, 0.21%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (6 samples, 0.21%)generic_array::ArrayBuilder<T,N>::iter_position (2 samples, 0.07%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (10 samples, 0.35%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (6 samples, 0.21%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (3 samples, 0.10%)core::ptr::mut_ptr::<impl *mut T>::is_null (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (129 samples, 4.46%)<ciph..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (23 samples, 0.79%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (23 samples, 0.79%)core::iter::traits::iterator::Iterator::for_each (22 samples, 0.76%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (21 samples, 0.73%)core::iter::traits::iterator::Iterator::fold (21 samples, 0.73%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (6 samples, 0.21%)core::slice::iter::IterMut<T>::post_inc_start (3 samples, 0.10%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::result::Result<T,E>::map_err (1 samples, 0.03%)core::slice::<impl [T]>::copy_from_slice (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (4 samples, 0.14%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)core::ptr::write (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (6 samples, 0.21%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (6 samples, 0.21%)core::iter::traits::iterator::Iterator::for_each (6 samples, 0.21%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (6 samples, 0.21%)core::iter::traits::iterator::Iterator::fold (6 samples, 0.21%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.07%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (13 samples, 0.45%)universal_hash::UniversalHash::update (4 samples, 0.14%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (4 samples, 0.14%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (4 samples, 0.14%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (4 samples, 0.14%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (4 samples, 0.14%)poly1305::backend::soft::State::compute_block (4 samples, 0.14%)core::convert::num::<impl core::convert::From<u32> for u64>::from (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (95 samples, 3.28%)cor..core::core_arch::x86::m128iExt::as_i32x4 (18 samples, 0.62%)core::core_arch::x86::sse2::_mm_slli_epi32 (66 samples, 2.28%)c..core::core_arch::x86::m128iExt::as_i32x4 (13 samples, 0.45%)core::core_arch::x86::sse2::_mm_srli_epi32 (13 samples, 0.45%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.07%)chacha20::backends::sse2::add_xor_rot (507 samples, 17.52%)chacha20::backends::sse2::a..core::core_arch::x86::sse2::_mm_xor_si128 (64 samples, 2.21%)c..chacha20::backends::sse2::cols_to_rows (34 samples, 1.17%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (19 samples, 0.66%)core::core_arch::x86::m128iExt::as_i32x4 (4 samples, 0.14%)chacha20::backends::sse2::double_quarter_round (576 samples, 19.90%)chacha20::backends::sse2::doubl..chacha20::backends::sse2::rows_to_cols (31 samples, 1.07%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (24 samples, 0.83%)core::core_arch::x86::m128iExt::as_i32x4 (8 samples, 0.28%)core::core_arch::x86::sse2::_mm_add_epi32 (7 samples, 0.24%)core::core_arch::x86::m128iExt::as_i32x4 (4 samples, 0.14%)<usize as core::iter::range::Step>::forward_unchecked (4 samples, 0.14%)core::num::<impl usize>::unchecked_add (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (6 samples, 0.21%)core::ptr::read (3 samples, 0.10%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (28 samples, 0.97%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (25 samples, 0.86%)core::mem::replace (5 samples, 0.17%)core::ptr::write (1 samples, 0.03%)chacha20::backends::sse2::rounds (622 samples, 21.49%)chacha20::backends::sse2::roundsmemcpy (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_storeu_si128 (3 samples, 0.10%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (7 samples, 0.24%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (6 samples, 0.21%)core::mem::replace (3 samples, 0.10%)core::ptr::read (1 samples, 0.03%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (641 samples, 22.15%)<chacha20::backends::sse2::Backend<..core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.10%)core::ptr::mut_ptr::<impl *mut T>::offset (3 samples, 0.10%)<inout::inout_buf::InOutBufIter<T> as core::iter::traits::iterator::Iterator>::next (6 samples, 0.21%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::write (19 samples, 0.66%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (157 samples, 5.43%)<core::..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (89 samples, 3.08%)cor..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (66 samples, 2.28%)<..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (12 samples, 0.41%)<u8 as core::default::Default>::default (3 samples, 0.10%)core::ptr::mut_ptr::<impl *mut T>::is_null (38 samples, 1.31%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (19 samples, 0.66%)core::ptr::mut_ptr::<impl *mut T>::addr (13 samples, 0.45%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (27 samples, 0.93%)core::ptr::mut_ptr::<impl *mut T>::offset (23 samples, 0.79%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (384 samples, 13.27%)core::iter::traits::..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (384 samples, 13.27%)<core::iter::adapter..core::iter::traits::iterator::Iterator::fold (384 samples, 13.27%)core::iter::traits::..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (133 samples, 4.60%)<core..core::slice::iter::IterMut<T>::post_inc_start (69 samples, 2.38%)co..core::ptr::non_null::NonNull<T>::new_unchecked (7 samples, 0.24%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.07%)[libc.so.6] (2 samples, 0.07%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)_init (1 samples, 0.03%)[libc.so.6] (4 samples, 0.14%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (7 samples, 0.24%)memcpy (3 samples, 0.10%)generic_array::ArrayBuilder<T,N>::into_inner (16 samples, 0.55%)core::ptr::read (11 samples, 0.38%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (10 samples, 0.35%)memcpy (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (406 samples, 14.03%)generic_array::impls:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (406 samples, 14.03%)<generic_array::Gener..generic_array::ArrayBuilder<T,N>::iter_position (5 samples, 0.17%)core::slice::<impl [T]>::iter_mut (2 samples, 0.07%)core::slice::iter::IterMut<T>::new (2 samples, 0.07%)core::slice::<impl [T]>::as_mut_ptr (1 samples, 0.03%)core::ptr::const_ptr::<impl *const T>::cast (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (81 samples, 2.80%)<g..core::slice::raw::from_raw_parts (69 samples, 2.38%)co..core::ptr::slice_from_raw_parts (54 samples, 1.87%)c..core::ptr::metadata::from_raw_parts (42 samples, 1.45%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (47 samples, 1.62%)core::slice::raw::from_raw_parts_mut (36 samples, 1.24%)core::ptr::slice_from_raw_parts_mut (20 samples, 0.69%)core::ptr::metadata::from_raw_parts_mut (15 samples, 0.52%)<usize as core::iter::range::Step>::forward_unchecked (19 samples, 0.66%)core::num::<impl usize>::unchecked_add (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (12 samples, 0.41%)core::ptr::read (34 samples, 1.17%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (4 samples, 0.14%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (4 samples, 0.14%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (131 samples, 4.53%)core:..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (126 samples, 4.35%)<core..core::mem::replace (52 samples, 1.80%)c..core::ptr::write (5 samples, 0.17%)[libc.so.6] (2 samples, 0.07%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (3 samples, 0.10%)[libc.so.6] (2 samples, 0.07%)core::ptr::read (6 samples, 0.21%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (6 samples, 0.21%)memcpy (1 samples, 0.03%)core::ptr::write (20 samples, 0.69%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (184 samples, 6.36%)<core::i..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (116 samples, 4.01%)core..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (82 samples, 2.83%)<g..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (16 samples, 0.55%)<u8 as core::default::Default>::default (3 samples, 0.10%)core::ptr::mut_ptr::<impl *mut T>::is_null (27 samples, 0.93%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (14 samples, 0.48%)core::ptr::mut_ptr::<impl *mut T>::addr (10 samples, 0.35%)core::ptr::mut_ptr::<impl *mut T>::add (22 samples, 0.76%)core::ptr::mut_ptr::<impl *mut T>::offset (21 samples, 0.73%)core::iter::traits::iterator::Iterator::for_each (397 samples, 13.72%)core::iter::traits::i..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (397 samples, 13.72%)<core::iter::adapters..core::iter::traits::iterator::Iterator::fold (396 samples, 13.68%)core::iter::traits::i..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (118 samples, 4.08%)<cor..core::slice::iter::IterMut<T>::post_inc_start (61 samples, 2.11%)c..core::ptr::non_null::NonNull<T>::new_unchecked (6 samples, 0.21%)[libc.so.6] (2 samples, 0.07%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.10%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (2 samples, 0.07%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (4 samples, 0.14%)[libc.so.6] (2 samples, 0.07%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (8 samples, 0.28%)memcpy (2 samples, 0.07%)generic_array::ArrayBuilder<T,N>::into_inner (16 samples, 0.55%)core::ptr::read (11 samples, 0.38%)memcpy (2 samples, 0.07%)generic_array::ArrayBuilder<T,N>::iter_position (6 samples, 0.21%)core::slice::<impl [T]>::iter_mut (5 samples, 0.17%)core::slice::iter::IterMut<T>::new (5 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::is_null (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (1,966 samples, 67.93%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,966 samples, 67.93%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,966 samples, 67.93%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backendchacha20::backends::sse2::inner (1,966 samples, 67.93%)chacha20::backends::sse2::inner<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (1,966 samples, 67.93%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::callinout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (913 samples, 31.55%)inout::inout::InOut<generic_array::GenericArray<u8,..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (423 samples, 14.62%)generic_array::impls::..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (423 samples, 14.62%)<generic_array::Generi..generic_array::ArrayBuilder<T,N>::new (1 samples, 0.03%)chacha20::avx2_cpuid::InitToken::get (1 samples, 0.03%)core::sync::atomic::AtomicU8::load (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (9 samples, 0.31%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_slli_epi32 (5 samples, 0.17%)core::core_arch::x86::m128iExt::as_i32x4 (3 samples, 0.10%)chacha20::backends::sse2::add_xor_rot (27 samples, 0.93%)core::core_arch::x86::sse2::_mm_xor_si128 (5 samples, 0.17%)cipher::stream_core::StreamCipherCore::write_keystream_block (31 samples, 1.07%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (31 samples, 1.07%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (31 samples, 1.07%)chacha20::backends::sse2::inner (30 samples, 1.04%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (29 samples, 1.00%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (29 samples, 1.00%)chacha20::backends::sse2::rounds (29 samples, 1.00%)chacha20::backends::sse2::double_quarter_round (28 samples, 0.97%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.03%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (3 samples, 0.10%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.07%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.07%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (2,012 samples, 69.52%)cipher::stream::StreamCipher::apply_keystreamcipher::stream::StreamCipher::try_apply_keystream (2,012 samples, 69.52%)cipher::stream::StreamCipher::try_apply_keystream<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (2,012 samples, 69.52%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inoutinout::inout_buf::InOutBuf<u8>::xor_in2out (11 samples, 0.38%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<Z as zeroize::Zeroize>::zeroize (1 samples, 0.03%)zeroize::atomic_fence (1 samples, 0.03%)core::sync::atomic::compiler_fence (1 samples, 0.03%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)core::num::<impl usize>::unchecked_add (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.03%)core::ptr::read (2 samples, 0.07%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (11 samples, 0.38%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (10 samples, 0.35%)core::mem::replace (5 samples, 0.17%)core::ptr::write (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (16 samples, 0.55%)<[Z] as zeroize::Zeroize>::zeroize (15 samples, 0.52%)zeroize::volatile_set (15 samples, 0.52%)core::ptr::write_volatile (2 samples, 0.07%)<&mut I as core::iter::traits::iterator::Iterator>::next (5 samples, 0.17%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.17%)core::slice::iter::IterMut<T>::post_inc_start (4 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::offset (2 samples, 0.07%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (23 samples, 0.79%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (7 samples, 0.24%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (7 samples, 0.24%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (7 samples, 0.24%)<[Z: N] as zeroize::Zeroize>::zeroize (7 samples, 0.24%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (7 samples, 0.24%)<Z as zeroize::Zeroize>::zeroize (1 samples, 0.03%)zeroize::volatile_write (1 samples, 0.03%)core::ptr::write_volatile (1 samples, 0.03%)core::result::Result<T,E>::is_ok (1 samples, 0.03%)core::slice::raw::from_ref (1 samples, 0.03%)core::array::from_ref (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (5 samples, 0.17%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (5 samples, 0.17%)core::iter::traits::iterator::Iterator::fold (5 samples, 0.17%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.07%)core::slice::iter::IterMut<T>::post_inc_start (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (7 samples, 0.24%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (7 samples, 0.24%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (8 samples, 0.28%)core::slice::iter::Iter<T>::post_inc_start (2 samples, 0.07%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (15 samples, 0.52%)<T as core::convert::TryInto<U>>::try_into (120 samples, 4.15%)<T as..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (106 samples, 3.66%)core..core::result::Result<T,E>::map (73 samples, 2.52%)co..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (18 samples, 0.62%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (7 samples, 0.24%)core::slice::raw::from_raw_parts (6 samples, 0.21%)core::ptr::slice_from_raw_parts (4 samples, 0.14%)core::ptr::metadata::from_raw_parts (4 samples, 0.14%)core::convert::num::<impl core::convert::From<u32> for u64>::from (4 samples, 0.14%)core::num::<impl u32>::from_le_bytes (25 samples, 0.86%)core::num::<impl u32>::from_ne_bytes (15 samples, 0.52%)core::result::Result<T,E>::unwrap (47 samples, 1.62%)core::ptr::const_ptr::<impl *const T>::add (4 samples, 0.14%)core::ptr::const_ptr::<impl *const T>::offset (4 samples, 0.14%)core::ptr::const_ptr::<impl *const [T]>::as_ptr (2 samples, 0.07%)core::ptr::const_ptr::<impl *const T>::cast (3 samples, 0.10%)universal_hash::UniversalHash::update (386 samples, 13.34%)universal_hash::Univ..<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (386 samples, 13.34%)<poly1305::Poly1305 ..<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (386 samples, 13.34%)<poly1305::backend::..<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (385 samples, 13.30%)<universal_hash::Uni..<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (374 samples, 12.92%)<poly1305::backend:..poly1305::backend::soft::State::compute_block (374 samples, 12.92%)poly1305::backend::..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (49 samples, 1.69%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (46 samples, 1.59%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (38 samples, 1.31%)core::ptr::slice_from_raw_parts (20 samples, 0.69%)core::ptr::metadata::from_raw_parts (14 samples, 0.48%)core::slice::<impl [T]>::split_at (1 samples, 0.03%)core::slice::<impl [T]>::split_at_unchecked (1 samples, 0.03%)universal_hash::UniversalHash::update_padded (396 samples, 13.68%)universal_hash::Unive..universal_hash::to_blocks (2 samples, 0.07%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.07%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (2 samples, 0.07%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.03%)<[T] as subtle::ConstantTimeEq>::ct_eq (4 samples, 0.14%)core::slice::<impl [T]>::iter (1 samples, 0.03%)core::slice::iter::Iter<T>::new (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.10%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (3 samples, 0.10%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.07%)core::iter::traits::iterator::Iterator::for_each (7 samples, 0.24%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (6 samples, 0.21%)core::iter::traits::iterator::Iterator::fold (6 samples, 0.21%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (2,462 samples, 85.07%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detacheduniversal_hash::UniversalHash::verify (16 samples, 0.55%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (12 samples, 0.41%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (11 samples, 0.38%)poly1305::backend::soft::State::finalize_mut (11 samples, 0.38%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (8 samples, 0.28%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (8 samples, 0.28%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)<[Z] as zeroize::Zeroize>::zeroize (3 samples, 0.10%)zeroize::volatile_set (3 samples, 0.10%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::new (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.03%)core::result::Result<T,E>::map (1 samples, 0.03%)<poly1305::backend::soft::State as core::default::Default>::default (2 samples, 0.07%)core::array::<impl core::default::Default for [T: _]>::default (2 samples, 0.07%)core::num::<impl u32>::from_le_bytes (1 samples, 0.03%)core::num::<impl u32>::from_ne_bytes (1 samples, 0.03%)core::result::Result<T,E>::unwrap (1 samples, 0.03%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (10 samples, 0.35%)poly1305::backend::autodetect::State::new (10 samples, 0.35%)poly1305::backend::soft::State::new (9 samples, 0.31%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (3 samples, 0.10%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (3 samples, 0.10%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.10%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.10%)chacha20::backends::sse2::inner (3 samples, 0.10%)core::core_arch::x86::sse2::_mm_add_epi32 (8 samples, 0.28%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.07%)core::core_arch::x86::sse2::_mm_slli_epi32 (4 samples, 0.14%)core::core_arch::x86::sse2::_mm_srli_epi32 (2 samples, 0.07%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)chacha20::backends::sse2::add_xor_rot (29 samples, 1.00%)core::core_arch::x86::sse2::_mm_xor_si128 (4 samples, 0.14%)chacha20::backends::sse2::double_quarter_round (30 samples, 1.04%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.03%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)chacha20::backends::sse2::rounds (32 samples, 1.11%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.07%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (35 samples, 1.21%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (35 samples, 1.21%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (35 samples, 1.21%)chacha20::backends::sse2::inner (35 samples, 1.21%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (35 samples, 1.21%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (35 samples, 1.21%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.03%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::convert::num::ptr_try_from_impls::<impl core::convert::TryFrom<u32> for usize>::try_from (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (3 samples, 0.10%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (2 samples, 0.07%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (2 samples, 0.07%)core::result::Result<T,E>::ok (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::set_pos_unchecked (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.07%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.07%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.14%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.14%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (54 samples, 1.87%)c..cipher::stream::StreamCipher::try_apply_keystream (54 samples, 1.87%)c..<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (54 samples, 1.87%)<..inout::inout_buf::InOutBuf<u8>::xor_in2out (6 samples, 0.21%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)cipher::stream::StreamCipherSeek::seek (6 samples, 0.21%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipherSeek>::try_seek (6 samples, 0.21%)<u64 as cipher::stream::SeekNum>::into_block_byte (5 samples, 0.17%)core::convert::num::<impl core::convert::TryFrom<u64> for u32>::try_from (1 samples, 0.03%)generic_array::GenericArray<T,N>::from_slice (1 samples, 0.03%)core::ptr::write (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (7 samples, 0.24%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (5 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (4 samples, 0.14%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (8 samples, 0.28%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (8 samples, 0.28%)core::iter::traits::iterator::Iterator::fold (8 samples, 0.28%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (3 samples, 0.10%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (2,679 samples, 92.57%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detachedchacha20poly1305::cipher::Cipher<C>::new (87 samples, 3.01%)cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (12 samples, 0.41%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (12 samples, 0.41%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.03%)<heapless::vec::Vec<u8,_> as aead::Buffer>::truncate (1 samples, 0.03%)heapless::vec::Vec<T,_>::truncate (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)aead::AeadInPlace::decrypt_in_place (2,683 samples, 92.71%)aead::AeadInPlace::decrypt_in_place<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (2 samples, 0.07%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (2 samples, 0.07%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (2 samples, 0.07%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (2,783 samples, 96.16%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_fromtftp::encryption::Encryptor::decrypt (2,685 samples, 92.78%)tftp::encryption::Encryptor::decryptcore::result::Result<T,E>::map_err (1 samples, 0.03%)<tftp::std_compat::io::ErrorKind as core::cmp::PartialEq>::eq (1 samples, 0.03%)core::cmp::PartialOrd::gt (2 samples, 0.07%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (1 samples, 0.03%)heapless::vec::Vec<T,_>::set_len (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.03%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (4 samples, 0.14%)core::num::<impl u32>::from_le_bytes (1 samples, 0.03%)core::num::<impl u32>::from_ne_bytes (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.07%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (2 samples, 0.07%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)chacha20::xchacha::quarter_round (8 samples, 0.28%)core::num::<impl u32>::rotate_left (1 samples, 0.03%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)chacha20::xchacha::hchacha (14 samples, 0.48%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (20 samples, 0.69%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (2 samples, 0.07%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (2 samples, 0.07%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.07%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.07%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.07%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (22 samples, 0.76%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (2 samples, 0.07%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (2 samples, 0.07%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.07%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.07%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.07%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.07%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.07%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.07%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (1 samples, 0.03%)poly1305::backend::soft::State::finalize_mut (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (1 samples, 0.03%)universal_hash::UniversalHash::update (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.03%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.03%)poly1305::backend::soft::State::compute_block (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (5 samples, 0.17%)cipher::stream::StreamCipher::try_apply_keystream (5 samples, 0.17%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (5 samples, 0.17%)cipher::stream_core::StreamCipherCore::write_keystream_block (5 samples, 0.17%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.17%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.17%)chacha20::backends::sse2::inner (5 samples, 0.17%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (5 samples, 0.17%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (5 samples, 0.17%)chacha20::backends::sse2::rounds (5 samples, 0.17%)chacha20::backends::sse2::double_quarter_round (5 samples, 0.17%)chacha20::backends::sse2::add_xor_rot (5 samples, 0.17%)core::core_arch::x86::sse2::_mm_add_epi32 (3 samples, 0.10%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (2 samples, 0.07%)<[Z] as zeroize::Zeroize>::zeroize (2 samples, 0.07%)zeroize::volatile_set (2 samples, 0.07%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.07%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (3 samples, 0.10%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.03%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.03%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (1 samples, 0.03%)<[Z: N] as zeroize::Zeroize>::zeroize (1 samples, 0.03%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (1 samples, 0.03%)<&mut I as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (12 samples, 0.41%)universal_hash::UniversalHash::update_padded (2 samples, 0.07%)universal_hash::UniversalHash::update (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.03%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.03%)poly1305::backend::soft::State::compute_block (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<[Z] as zeroize::Zeroize>::zeroize (3 samples, 0.10%)zeroize::volatile_set (3 samples, 0.10%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.07%)core::ptr::mut_ptr::<impl *mut T>::offset (2 samples, 0.07%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.03%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (3 samples, 0.10%)poly1305::backend::autodetect::State::new (3 samples, 0.10%)poly1305::backend::soft::State::new (3 samples, 0.10%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.07%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.07%)core::result::Result<T,E>::map (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.03%)chacha20::backends::sse2::double_quarter_round (4 samples, 0.14%)chacha20::backends::sse2::add_xor_rot (4 samples, 0.14%)core::core_arch::x86::sse2::_mm_xor_si128 (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (6 samples, 0.21%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (6 samples, 0.21%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (6 samples, 0.21%)chacha20::backends::sse2::inner (6 samples, 0.21%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (6 samples, 0.21%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (6 samples, 0.21%)chacha20::backends::sse2::rounds (6 samples, 0.21%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.07%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.07%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)inout::inout_buf::InOutBuf<T>::into_chunks (1 samples, 0.03%)inout::inout_buf::InOutBuf<T>::len (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (8 samples, 0.28%)cipher::stream::StreamCipher::try_apply_keystream (8 samples, 0.28%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (8 samples, 0.28%)inout::inout_buf::InOutBuf<u8>::xor_in2out (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.07%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.07%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.07%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.07%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)core::ptr::write (1 samples, 0.03%)aead::AeadInPlace::encrypt_in_place (52 samples, 1.80%)a..<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (52 samples, 1.80%)<..chacha20poly1305::cipher::Cipher<C>::new (18 samples, 0.62%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.10%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.10%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (53 samples, 1.83%)<..tftp::encryption::Encryptor::encrypt (53 samples, 1.83%)t..core::result::Result<T,E>::map_err (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<tftp::io::StdCompatFile as tftp::std_compat::io::Write>::write (1 samples, 0.03%)tftp::map::Map<K,V,_>::get (1 samples, 0.03%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (1 samples, 0.03%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::option::Option<T>::and_then (1 samples, 0.03%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (2 samples, 0.07%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (2 samples, 0.07%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (2 samples, 0.07%)tftp::map::Map<K,V,_>::remove (6 samples, 0.21%)tftp::map::Map<K,V,_>::iter (3 samples, 0.10%)<&tftp::map::Map<K,V,_> as core::iter::traits::collect::IntoIterator>::into_iter (3 samples, 0.10%)core::slice::<impl [T]>::iter (1 samples, 0.03%)core::slice::iter::Iter<T>::new (1 samples, 0.03%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.03%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (11 samples, 0.38%)tftp::storage::BlockMapper::index (1 samples, 0.03%)tftp::client::client::write_block (66 samples, 2.28%)t..log::max_level (1 samples, 0.03%)core::sync::atomic::AtomicUsize::load (1 samples, 0.03%)core::sync::atomic::atomic_load (1 samples, 0.03%)core::ops::function::FnOnce::call_once (2 samples, 0.07%)tftp::instant_callback::{{closure}} (2 samples, 0.07%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.03%)clock_gettime (1 samples, 0.03%)tftp::instant_callback (5 samples, 0.17%)tftp::std_compat::time::Instant::from_time (4 samples, 0.14%)core::time::Duration::from_micros (1 samples, 0.03%)core::time::Duration::new (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)tftp::packet::PacketType::from_bytes (6 samples, 0.21%)tftp::packet::try_from (4 samples, 0.14%)core::option::Option<T>::ok_or (2 samples, 0.07%)core::ptr::drop_in_place<tftp::error::PacketError> (1 samples, 0.03%)all (2,894 samples, 100%)tftp (2,894 samples, 100.00%)tftp[unknown] (2,887 samples, 99.76%)[unknown]tftp::client::client::receive_file (2,880 samples, 99.52%)tftp::client::client::receive_filetftp::std_compat::time::Instant::elapsed (1 samples, 0.03%)core::time::Duration::from_micros (1 samples, 0.03%)core::time::Duration::new (1 samples, 0.03%)core::num::<impl u64>::checked_add (1 samples, 0.03%) \ No newline at end of file diff --git a/info/receive_flamegraph_no_encryption_alloc.svg b/info/receive_flamegraph_no_encryption_alloc.svg new file mode 100644 index 0000000..4500e60 --- /dev/null +++ b/info/receive_flamegraph_no_encryption_alloc.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [[stack]] (2 samples, 1.59%)write (2 samples, 1.59%)[unknown] (2 samples, 1.59%)[ld-linux-x86-64.so.2] (1 samples, 0.79%)[ld-linux-x86-64.so.2] (1 samples, 0.79%)[ld-linux-x86-64.so.2] (1 samples, 0.79%)[ld-linux-x86-64.so.2] (6 samples, 4.76%)[ld-li..[unknown] (1 samples, 0.79%)exit (1 samples, 0.79%)[libc.so.6] (1 samples, 0.79%)__call_tls_dtors (1 samples, 0.79%)std::thread::local::fast::destroy_value (1 samples, 0.79%)std::panic::catch_unwind (1 samples, 0.79%)std::panicking::try (1 samples, 0.79%)__rust_try (1 samples, 0.79%)std::panicking::try::do_call (1 samples, 0.79%)<core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (1 samples, 0.79%)core::ops::function::FnOnce::call_once (1 samples, 0.79%)std::thread::local::fast::destroy_value::{{closure}} (1 samples, 0.79%)core::mem::drop (1 samples, 0.79%)core::ptr::drop_in_place<core::option::Option<core::cell::RefCell<core::option::Option<env_logger::fmt::Formatter>>>> (1 samples, 0.79%)core::ptr::drop_in_place<core::cell::RefCell<core::option::Option<env_logger::fmt::Formatter>>> (1 samples, 0.79%)core::ptr::drop_in_place<core::cell::UnsafeCell<core::option::Option<env_logger::fmt::Formatter>>> (1 samples, 0.79%)core::ptr::drop_in_place<core::option::Option<env_logger::fmt::Formatter>> (1 samples, 0.79%)core::ptr::drop_in_place<env_logger::fmt::Formatter> (1 samples, 0.79%)core::ptr::drop_in_place<alloc::rc::Rc<core::cell::RefCell<env_logger::fmt::writer::termcolor::imp::Buffer>>> (1 samples, 0.79%)<alloc::rc::Rc<T> as core::ops::drop::Drop>::drop (1 samples, 0.79%)core::ptr::drop_in_place<core::cell::RefCell<env_logger::fmt::writer::termcolor::imp::Buffer>> (1 samples, 0.79%)core::ptr::drop_in_place<core::cell::UnsafeCell<env_logger::fmt::writer::termcolor::imp::Buffer>> (1 samples, 0.79%)core::ptr::drop_in_place<env_logger::fmt::writer::termcolor::imp::Buffer> (1 samples, 0.79%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (2 samples, 1.59%)core::slice::raw::from_raw_parts (1 samples, 0.79%)core::ptr::slice_from_raw_parts (1 samples, 0.79%)core::ptr::metadata::from_raw_parts (1 samples, 0.79%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.79%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 1.59%)core::mem::size_of_val (2 samples, 1.59%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (4 samples, 3.17%)<tf..tftp::packet::PacketType::from_bytes (2 samples, 1.59%)tftp::packet::try_from (2 samples, 1.59%)core::slice::<impl [T]>::get (1 samples, 0.79%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.79%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.79%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (1 samples, 0.79%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (1 samples, 0.79%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.79%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (1 samples, 0.79%)alloc::alloc::dealloc (1 samples, 0.79%)__rust_dealloc (1 samples, 0.79%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.79%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.79%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.79%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.79%)core::result::Result<T,E>::map_err (4 samples, 3.17%)cor..core::ops::function::FnOnce::call_once (3 samples, 2.38%)co..tftp::io::from_io_err (3 samples, 2.38%)tf..std::io::error::Error::kind (2 samples, 1.59%)std::sys::unix::decode_error_kind (1 samples, 0.79%)<&T as polling::Source>::raw (1 samples, 0.79%)std::os::fd::net::<impl std::os::fd::raw::AsRawFd for std::net::udp::UdpSocket>::as_raw_fd (1 samples, 0.79%)<std::sys::unix::fs::File as std::os::fd::raw::AsRawFd>::as_raw_fd (1 samples, 0.79%)<std::sys::unix::fd::FileDesc as std::os::fd::raw::AsRawFd>::as_raw_fd (1 samples, 0.79%)<std::os::fd::owned::OwnedFd as std::os::fd::raw::AsRawFd>::as_raw_fd (1 samples, 0.79%)polling::Poller::modify (3 samples, 2.38%)po..polling::epoll::Poller::modify (2 samples, 1.59%)polling::epoll::Poller::ctl (1 samples, 0.79%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.79%)core::iter::traits::iterator::Iterator::find (1 samples, 0.79%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (1 samples, 0.79%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.79%)alloc::raw_vec::RawVec<T,A>::needs_to_grow (1 samples, 0.79%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.79%)alloc::alloc::alloc (2 samples, 1.59%)malloc (2 samples, 1.59%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (3 samples, 2.38%)<a..alloc::alloc::Global::alloc_impl (3 samples, 2.38%)al..core::ptr::non_null::NonNull<T>::new (1 samples, 0.79%)alloc::raw_vec::finish_grow (4 samples, 3.17%)all..<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.79%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (8 samples, 6.35%)<alloc::..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (8 samples, 6.35%)<alloc::..alloc::vec::Vec<T,A>::extend_desugared (8 samples, 6.35%)alloc::v..alloc::vec::Vec<T,A>::reserve (7 samples, 5.56%)alloc::..alloc::raw_vec::RawVec<T,A>::reserve (7 samples, 5.56%)alloc::..alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (6 samples, 4.76%)alloc:..alloc::raw_vec::RawVec<T,A>::grow_amortized (6 samples, 4.76%)alloc:..core::cmp::max (1 samples, 0.79%)core::cmp::Ord::max (1 samples, 0.79%)core::cmp::max_by (1 samples, 0.79%)<std::sync::mutex::MutexGuard<T> as core::ops::deref::Deref>::deref (1 samples, 0.79%)core::ptr::drop_in_place<std::sync::mutex::MutexGuard<polling::epoll::Events>> (1 samples, 0.79%)<std::sync::mutex::MutexGuard<T> as core::ops::drop::Drop>::drop (1 samples, 0.79%)polling::epoll::Events::iter (2 samples, 1.59%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (1 samples, 0.79%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.79%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.79%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.79%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.79%)<T as core::convert::Into<U>>::into (1 samples, 0.79%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (3 samples, 2.38%)<c..<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 1.59%)[libc.so.6] (1 samples, 0.79%)epoll_wait (26 samples, 20.63%)epoll_wait<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.79%)polling::epoll::Poller::wait (41 samples, 32.54%)polling::epoll::Poller::waitpolling::epoll::Poller::modify (3 samples, 2.38%)po..polling::epoll::Poller::ctl (3 samples, 2.38%)po..core::option::Option<T>::map (2 samples, 1.59%)polling::Poller::wait (57 samples, 45.24%)polling::Poller::waitstd::sync::mutex::Mutex<T>::try_lock (3 samples, 2.38%)st..std::sync::mutex::MutexGuard<T>::new (1 samples, 0.79%)std::sync::poison::Flag::guard (1 samples, 0.79%)std::sync::poison::Flag::get (1 samples, 0.79%)core::sync::atomic::AtomicBool::load (1 samples, 0.79%)core::sync::atomic::atomic_load (1 samples, 0.79%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (71 samples, 56.35%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_fromstd::net::udp::UdpSocket::recv_from (2 samples, 1.59%)std::sys_common::net::UdpSocket::recv_from (1 samples, 0.79%)std::sys::unix::net::Socket::recv_from (1 samples, 0.79%)std::sys::unix::net::Socket::recv_from_with_flags (1 samples, 0.79%)std::sys::unix::cvt (1 samples, 0.79%)std::io::error::Error::last_os_error (1 samples, 0.79%)std::sys::unix::os::errno (1 samples, 0.79%)__errno_location (1 samples, 0.79%)alloc::vec::Vec<T,A>::resize (1 samples, 0.79%)alloc::vec::Vec<T,A>::truncate (1 samples, 0.79%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.79%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.79%)core::cmp::PartialOrd::gt (2 samples, 1.59%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (1 samples, 0.79%)core::cmp::impls::<impl core::cmp::PartialOrd for u64>::partial_cmp (1 samples, 0.79%)tftp::client::client::query_server (1 samples, 0.79%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (1 samples, 0.79%)<tftp::packet::OptionalAck as tftp::packet::ByteConverter>::from_bytes (1 samples, 0.79%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (1 samples, 0.79%)alloc::collections::btree::map::entry::VacantEntry<K,V,A>::insert (1 samples, 0.79%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Owned,K,V,alloc::collections::btree::node::marker::Leaf>::new_leaf (1 samples, 0.79%)alloc::collections::btree::node::LeafNode<K,V>::new (1 samples, 0.79%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.79%)alloc::vec::Vec<T,A>::allocator (1 samples, 0.79%)alloc::raw_vec::RawVec<T,A>::allocator (1 samples, 0.79%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (2 samples, 1.59%)core::iter::traits::iterator::Iterator::collect (2 samples, 1.59%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 1.59%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (2 samples, 1.59%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (2 samples, 1.59%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 1.59%)<core::array::iter::IntoIter<T,_> as core::iter::traits::exact_size::ExactSizeIterator>::len (2 samples, 1.59%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init_read (1 samples, 0.79%)core::ptr::const_ptr::<impl *const T>::read (1 samples, 0.79%)core::ptr::read (1 samples, 0.79%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.79%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (6 samples, 4.76%)<tftp:..core::iter::traits::iterator::Iterator::collect (2 samples, 1.59%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 1.59%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (2 samples, 1.59%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (2 samples, 1.59%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (2 samples, 1.59%)alloc::vec::Vec<T,A>::extend_trusted (2 samples, 1.59%)core::iter::traits::iterator::Iterator::for_each (2 samples, 1.59%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (2 samples, 1.59%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (2 samples, 1.59%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 1.59%)core::iter::traits::iterator::Iterator::try_fold (2 samples, 1.59%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (2 samples, 1.59%)core::ops::function::Fn::call (2 samples, 1.59%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (2 samples, 1.59%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (2 samples, 1.59%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.79%)alloc::collections::btree::map::BTreeMap<K,V,A>::len (1 samples, 0.79%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (2 samples, 1.59%)core::option::Option<T>::map (1 samples, 0.79%)tftp::client::client::write_block (17 samples, 13.49%)tftp::client::client..<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (10 samples, 7.94%)<tftp::stor..tftp::storage::BlockMapper::index (2 samples, 1.59%)core::time::Duration::as_micros (1 samples, 0.79%)tftp::instant_callback (7 samples, 5.56%)tftp::i..tftp::std_compat::time::Instant::from_time (6 samples, 4.76%)tftp::..core::ops::function::FnOnce::call_once (4 samples, 3.17%)cor..tftp::instant_callback::{{closure}} (4 samples, 3.17%)tft..std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (3 samples, 2.38%)st..clock_gettime (2 samples, 1.59%)__vdso_clock_gettime (1 samples, 0.79%)<T as core::convert::TryInto<U>>::try_into (2 samples, 1.59%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 1.59%)core::result::Result<T,E>::map (2 samples, 1.59%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.79%)tftp::packet::PacketType::from_bytes (5 samples, 3.97%)tftp..tftp::packet::try_from (5 samples, 3.97%)tftp..core::slice::<impl [T]>::get (2 samples, 1.59%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (2 samples, 1.59%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.79%)std::panic::catch_unwind (116 samples, 92.06%)std::panic::catch_unwindstd::panicking::try (116 samples, 92.06%)std::panicking::trystd::panicking::try::do_call (116 samples, 92.06%)std::panicking::try::do_callcore::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (116 samples, 92.06%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_oncestd::rt::lang_start::{{closure}} (116 samples, 92.06%)std::rt::lang_start::{{closure}}std::sys_common::backtrace::__rust_begin_short_backtrace (116 samples, 92.06%)std::sys_common::backtrace::__rust_begin_short_backtracecore::ops::function::FnOnce::call_once (116 samples, 92.06%)core::ops::function::FnOnce::call_oncetftp::main (116 samples, 92.06%)tftp::maintftp::start_receive (116 samples, 92.06%)tftp::start_receivetftp::client::client::receive_file (116 samples, 92.06%)tftp::client::client::receive_filetftp::std_compat::time::Instant::elapsed (1 samples, 0.79%)core::ops::function::FnOnce::call_once (1 samples, 0.79%)tftp::instant_callback::{{closure}} (1 samples, 0.79%)all (126 samples, 100%)tftp (126 samples, 100.00%)tftp_start (118 samples, 93.65%)_start__libc_start_main (118 samples, 93.65%)__libc_start_main[libc.so.6] (118 samples, 93.65%)[libc.so.6]main (117 samples, 92.86%)mainstd::rt::lang_start (117 samples, 92.86%)std::rt::lang_startstd::rt::lang_start_internal (117 samples, 92.86%)std::rt::lang_start_internalstd::panic::catch_unwind (117 samples, 92.86%)std::panic::catch_unwindstd::panicking::try (117 samples, 92.86%)std::panicking::trystd::panicking::try::do_call (117 samples, 92.86%)std::panicking::try::do_callstd::rt::lang_start_internal::{{closure}} (117 samples, 92.86%)std::rt::lang_start_internal::{{closure}}std::rt::init (1 samples, 0.79%)std::sys::unix::thread::guard::init (1 samples, 0.79%)std::sys::unix::thread::guard::get_stack_start_aligned (1 samples, 0.79%)std::sys::unix::thread::guard::get_stack_start (1 samples, 0.79%)pthread_getattr_np (1 samples, 0.79%)__getdelim (1 samples, 0.79%) \ No newline at end of file diff --git a/info/receive_flamegraph_no_encryption_stack.svg b/info/receive_flamegraph_no_encryption_stack.svg new file mode 100644 index 0000000..62506dc --- /dev/null +++ b/info/receive_flamegraph_no_encryption_stack.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [[heap]] (1 samples, 0.30%)epoll_ctl (1 samples, 0.30%)[unknown] (1 samples, 0.30%)[ld-linux-x86-64.so.2] (1 samples, 0.30%)[ld-linux-x86-64.so.2] (1 samples, 0.30%)[ld-linux-x86-64.so.2] (1 samples, 0.30%)[ld-linux-x86-64.so.2] (6 samples, 1.82%)[..[unknown] (1 samples, 0.30%)<tftp::cli::ClientCliConfig as clap::derive::Args>::augment_args (1 samples, 0.30%)<once_cell::sync::Lazy<T,F> as core::ops::deref::Deref>::deref (1 samples, 0.30%)once_cell::sync::Lazy<T,F>::force (1 samples, 0.30%)once_cell::sync::OnceCell<T>::get_or_init (1 samples, 0.30%)once_cell::sync::OnceCell<T>::get_or_try_init (1 samples, 0.30%)once_cell::imp::OnceCell<T>::initialize (1 samples, 0.30%)once_cell::imp::initialize_or_wait (1 samples, 0.30%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.30%)once_cell::imp::OnceCell<T>::initialize::{{closure}} (1 samples, 0.30%)once_cell::sync::OnceCell<T>::get_or_init::{{closure}} (1 samples, 0.30%)once_cell::sync::Lazy<T,F>::force::{{closure}} (1 samples, 0.30%)core::ops::function::FnOnce::call_once (1 samples, 0.30%)core::ops::function::FnOnce::call_once (1 samples, 0.30%)<tftp::cli::ClientCliConfig as clap::derive::Args>::augment_args::DEFAULT_VALUE::{{closure}} (1 samples, 0.30%)<T as alloc::string::ToString>::to_string (1 samples, 0.30%)core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (1 samples, 0.30%)core::fmt::num::imp::fmt_u64 (1 samples, 0.30%)<alloc::string::String as core::fmt::Write>::write_str (1 samples, 0.30%)alloc::string::String::push_str (1 samples, 0.30%)alloc::vec::Vec<T,A>::extend_from_slice (1 samples, 0.30%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<&T,core::slice::iter::Iter<T>>>::spec_extend (1 samples, 0.30%)alloc::vec::Vec<T,A>::append_elements (1 samples, 0.30%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.30%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.30%)<core::ops::index_range::IndexRange as core::iter::traits::iterator::Iterator>::next (1 samples, 0.30%)<&mut I as core::iter::traits::exact_size::ExactSizeIterator>::len (1 samples, 0.30%)heapless::vec::Vec<T,_>::new (1 samples, 0.30%)[libc.so.6] (1 samples, 0.30%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (3 samples, 0.91%)core::iter::traits::iterator::Iterator::collect (3 samples, 0.91%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (3 samples, 0.91%)heapless::vec::Vec<T,_>::push (1 samples, 0.30%)core::array::iter::<impl core::iter::traits::collect::IntoIterator for [T: N]>::into_iter (1 samples, 0.30%)core::mem::transmute_copy (1 samples, 0.30%)core::ptr::read (1 samples, 0.30%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.30%)core::iter::traits::iterator::Iterator::chain (2 samples, 0.61%)core::iter::adapters::chain::Chain<A,B>::new (2 samples, 0.61%)[libc.so.6] (2 samples, 0.61%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (8 samples, 2.43%)<t..core::iter::traits::iterator::Iterator::collect (2 samples, 0.61%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (1 samples, 0.30%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.30%)core::option::Option<T>::or_else (1 samples, 0.30%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next::{{closure}} (1 samples, 0.30%)<heapless::vec::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.30%)recvfrom (1 samples, 0.30%)[unknown] (1 samples, 0.30%)<T as core::convert::Into<U>>::into (2 samples, 0.61%)<core::option::Option<T> as core::convert::From<T>>::from (2 samples, 0.61%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.30%)core::option::Option<T>::ok_or (2 samples, 0.61%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.61%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.61%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.30%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (9 samples, 2.74%)<t..tftp::packet::try_from (4 samples, 1.22%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.30%)core::slice::<impl [T]>::get (1 samples, 0.30%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.30%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.30%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.91%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (3 samples, 0.91%)core::result::Result<T,E>::map (2 samples, 0.61%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (16 samples, 4.86%)<tftp:..tftp::packet::PacketType::from_bytes (6 samples, 1.82%)t..tftp::packet::try_from (6 samples, 1.82%)t..core::slice::<impl [T]>::get (3 samples, 0.91%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (3 samples, 0.91%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (3 samples, 0.91%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.30%)<heapless::vec::Vec<T,_> as core::ops::deref::DerefMut>::deref_mut (3 samples, 0.91%)heapless::vec::Vec<T,_>::as_mut_slice (1 samples, 0.30%)alloc::vec::Vec<T>::new (2 samples, 0.61%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.30%)alloc::raw_vec::RawVec<T,A>::ptr (1 samples, 0.30%)core::ptr::unique::Unique<T>::as_ptr (1 samples, 0.30%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.30%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.61%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.30%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.30%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (4 samples, 1.22%)alloc::alloc::dealloc (3 samples, 0.91%)cfree (3 samples, 0.91%)[libc.so.6] (2 samples, 0.61%)<T as core::convert::Into<U>>::into (2 samples, 0.61%)<core::ptr::non_null::NonNull<T> as core::convert::From<core::ptr::unique::Unique<T>>>::from (1 samples, 0.30%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (10 samples, 3.04%)cor..core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (8 samples, 2.43%)co..<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (8 samples, 2.43%)<a..alloc::raw_vec::RawVec<T,A>::current_memory (4 samples, 1.22%)core::result::Result<T,E>::unwrap_unchecked (1 samples, 0.30%)core::result::Result<T,E>::map (10 samples, 3.04%)cor..<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from::{{closure}} (5 samples, 1.52%)tftp::socket::std_to_socket_addr (5 samples, 1.52%)std::net::socket_addr::SocketAddrV4::ip (3 samples, 0.91%)core::ptr::drop_in_place<std::io::error::Error> (4 samples, 1.22%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (4 samples, 1.22%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (2 samples, 0.61%)std::io::error::repr_bitpacked::decode_repr (2 samples, 0.61%)std::io::error::repr_bitpacked::Repr::data (1 samples, 0.30%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.30%)core::result::Result<T,E>::map_err (14 samples, 4.26%)core:..core::ops::function::FnOnce::call_once (9 samples, 2.74%)co..tftp::io::from_io_err (9 samples, 2.74%)tf..std::io::error::Error::kind (5 samples, 1.52%)std::sys::unix::decode_error_kind (1 samples, 0.30%)<&T as polling::Source>::raw (2 samples, 0.61%)std::os::fd::net::<impl std::os::fd::raw::AsRawFd for std::net::udp::UdpSocket>::as_raw_fd (1 samples, 0.30%)<std::sys::unix::fs::File as std::sys_common::AsInner<std::sys::unix::fd::FileDesc>>::as_inner (1 samples, 0.30%)log::max_level (3 samples, 0.91%)core::sync::atomic::AtomicUsize::load (3 samples, 0.91%)core::sync::atomic::atomic_load (3 samples, 0.91%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.30%)core::option::Option<T>::map (3 samples, 0.91%)polling::epoll::Poller::ctl::{{closure}} (2 samples, 0.61%)polling::epoll::read_flags (1 samples, 0.30%)core::ptr::null_mut (1 samples, 0.30%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.30%)polling::Poller::modify (13 samples, 3.95%)poll..polling::epoll::Poller::modify (10 samples, 3.04%)pol..polling::epoll::Poller::ctl (6 samples, 1.82%)p..epoll_ctl (1 samples, 0.30%)core::iter::adapters::map::map_try_fold (1 samples, 0.30%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.61%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.30%)core::iter::traits::iterator::Iterator::find::check::{{closure}} (1 samples, 0.30%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.30%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (10 samples, 3.04%)<co..core::iter::traits::iterator::Iterator::find (10 samples, 3.04%)cor..<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (10 samples, 3.04%)<co..core::iter::traits::iterator::Iterator::try_fold (8 samples, 2.43%)co..core::iter::adapters::map::map_try_fold::{{closure}} (2 samples, 0.61%)polling::epoll::Events::iter::{{closure}} (1 samples, 0.30%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::size_hint (3 samples, 0.91%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::size_hint (3 samples, 0.91%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.30%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.30%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.30%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.30%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.30%)alloc::vec::Vec<T,A>::capacity (1 samples, 0.30%)alloc::raw_vec::RawVec<T,A>::capacity (1 samples, 0.30%)alloc::raw_vec::RawVec<T,A>::needs_to_grow (1 samples, 0.30%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.30%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.30%)alloc::alloc::alloc (9 samples, 2.74%)al..malloc (9 samples, 2.74%)ma..<alloc::alloc::Global as core::alloc::Allocator>::allocate (11 samples, 3.34%)<al..alloc::alloc::Global::alloc_impl (11 samples, 3.34%)all..core::ptr::non_null::NonNull<T>::new (1 samples, 0.30%)alloc::raw_vec::finish_grow (15 samples, 4.56%)alloc..core::result::Result<T,E>::map_err (1 samples, 0.30%)core::alloc::layout::Layout::array (2 samples, 0.61%)core::alloc::layout::Layout::array::inner (2 samples, 0.61%)core::cmp::max (2 samples, 0.61%)core::cmp::Ord::max (2 samples, 0.61%)core::cmp::max_by (2 samples, 0.61%)core::ops::function::FnOnce::call_once (2 samples, 0.61%)core::cmp::impls::<impl core::cmp::Ord for usize>::cmp (1 samples, 0.30%)alloc::raw_vec::RawVec<T,A>::grow_amortized (25 samples, 7.60%)alloc::raw..core::num::<impl usize>::checked_add (3 samples, 0.91%)core::num::<impl usize>::overflowing_add (1 samples, 0.30%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (49 samples, 14.89%)<alloc::vec::Vec<T,A> a..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (48 samples, 14.59%)<alloc::vec::Vec<T,A> ..alloc::vec::Vec<T,A>::extend_desugared (47 samples, 14.29%)alloc::vec::Vec<T,A>::..alloc::vec::Vec<T,A>::reserve (31 samples, 9.42%)alloc::vec::V..alloc::raw_vec::RawVec<T,A>::reserve (30 samples, 9.12%)alloc::raw_ve..alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (27 samples, 8.21%)alloc::raw_..alloc::raw_vec::handle_reserve (1 samples, 0.30%)<std::sync::mutex::MutexGuard<T> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.30%)core::iter::traits::iterator::Iterator::filter (1 samples, 0.30%)core::iter::adapters::filter::Filter<I,P>::new (1 samples, 0.30%)core::ptr::drop_in_place<std::sync::mutex::MutexGuard<polling::epoll::Events>> (4 samples, 1.22%)<std::sync::mutex::MutexGuard<T> as core::ops::drop::Drop>::drop (3 samples, 0.91%)std::sys::unix::locks::futex_mutex::Mutex::unlock (1 samples, 0.30%)core::sync::atomic::AtomicU32::swap (1 samples, 0.30%)core::sync::atomic::atomic_swap (1 samples, 0.30%)core::sync::atomic::AtomicBool::swap (2 samples, 0.61%)core::sync::atomic::atomic_swap (2 samples, 0.61%)log::max_level (1 samples, 0.30%)core::sync::atomic::AtomicUsize::load (1 samples, 0.30%)core::sync::atomic::atomic_load (1 samples, 0.30%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (6 samples, 1.82%)c..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (5 samples, 1.52%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (3 samples, 0.91%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.61%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.30%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.30%)core::ptr::const_ptr::<impl *const T>::offset (1 samples, 0.30%)polling::epoll::Events::iter (8 samples, 2.43%)po..core::iter::traits::iterator::Iterator::map (2 samples, 0.61%)core::iter::adapters::map::Map<I,F>::new (1 samples, 0.30%)<T as core::convert::Into<U>>::into (1 samples, 0.30%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.61%)<core::time::Duration as core::cmp::PartialEq>::eq (1 samples, 0.30%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (4 samples, 1.22%)[libc.so.6] (1 samples, 0.30%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (3 samples, 0.91%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.61%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (2 samples, 0.61%)core::time::Duration::as_secs (1 samples, 0.30%)core::time::Duration::from_secs (2 samples, 0.61%)core::time::Duration::new (1 samples, 0.30%)epoll_wait (30 samples, 9.12%)epoll_waitlog::max_level (4 samples, 1.22%)core::sync::atomic::AtomicUsize::load (2 samples, 0.61%)core::sync::atomic::atomic_load (2 samples, 0.61%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.30%)log::max_level (2 samples, 0.61%)core::sync::atomic::AtomicUsize::load (1 samples, 0.30%)core::sync::atomic::atomic_load (1 samples, 0.30%)core::option::Option<T>::as_mut (2 samples, 0.61%)polling::epoll::Poller::modify (13 samples, 3.95%)poll..polling::epoll::Poller::ctl (8 samples, 2.43%)po..core::option::Option<T>::map (5 samples, 1.52%)polling::epoll::Poller::ctl::{{closure}} (2 samples, 0.61%)read (3 samples, 0.91%)std::io::error::Error::last_os_error (1 samples, 0.30%)std::sys::unix::os::errno (1 samples, 0.30%)__errno_location (1 samples, 0.30%)polling::epoll::Poller::wait (71 samples, 21.58%)polling::epoll::Poller::waittimerfd_settime (1 samples, 0.30%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.30%)std::sync::mutex::MutexGuard<T>::new (1 samples, 0.30%)polling::Poller::wait (146 samples, 44.38%)polling::Poller::waitstd::sync::mutex::Mutex<T>::try_lock (6 samples, 1.82%)s..std::sys::unix::locks::futex_mutex::Mutex::try_lock (2 samples, 0.61%)core::sync::atomic::AtomicU32::compare_exchange (1 samples, 0.30%)core::sync::atomic::atomic_compare_exchange (1 samples, 0.30%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (205 samples, 62.31%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_fromstd::net::udp::UdpSocket::recv_from (4 samples, 1.22%)std::sys_common::net::UdpSocket::recv_from (3 samples, 0.91%)std::sys::unix::net::Socket::recv_from (3 samples, 0.91%)std::sys::unix::net::Socket::recv_from_with_flags (3 samples, 0.91%)recvfrom (3 samples, 0.91%)<tftp::std_compat::io::ErrorKind as core::cmp::PartialEq>::eq (2 samples, 0.61%)core::cmp::PartialEq::ne (3 samples, 0.91%)<tftp::std_compat::net::SocketAddr as core::cmp::PartialEq>::eq (2 samples, 0.61%)core::cmp::PartialOrd::gt (2 samples, 0.61%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (2 samples, 0.61%)core::time::Duration::from_millis (2 samples, 0.61%)core::time::Duration::new (1 samples, 0.30%)heapless::vec::Vec<T,_>::set_len (1 samples, 0.30%)log::max_level (3 samples, 0.91%)core::sync::atomic::AtomicUsize::load (3 samples, 0.91%)core::sync::atomic::atomic_load (2 samples, 0.61%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (1 samples, 0.30%)std::net::udp::UdpSocket::send_to (1 samples, 0.30%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::is_finished_below (1 samples, 0.30%)<tftp::io::StdCompatFile as tftp::std_compat::io::Write>::write (3 samples, 0.91%)std::os::unix::net::datagram::UnixDatagram::send (1 samples, 0.30%)<tftp::storage::BlockMapper as core::clone::Clone>::clone (2 samples, 0.61%)tftp::map::Map<K,V,_>::get (1 samples, 0.30%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::find (1 samples, 0.30%)core::option::Option<T>::and_then (2 samples, 0.61%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (2 samples, 0.61%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (1 samples, 0.30%)tftp::map::Map<K,V,_>::remove (8 samples, 2.43%)tf..tftp::map::Map<K,V,_>::iter (6 samples, 1.82%)t..<&tftp::map::Map<K,V,_> as core::iter::traits::collect::IntoIterator>::into_iter (6 samples, 1.82%)<..core::slice::<impl [T]>::iter (3 samples, 0.91%)core::slice::iter::Iter<T>::new (2 samples, 0.61%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (23 samples, 6.99%)<tftp::st..tftp::storage::BlockMapper::index (4 samples, 1.22%)[libc.so.6] (1 samples, 0.30%)tftp::client::client::write_block (28 samples, 8.51%)tftp::client..core::ptr::drop_in_place<heapless::vec::Vec<u8,1420_usize>> (1 samples, 0.30%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (7 samples, 2.13%)s..clock_gettime (6 samples, 1.82%)c..__vdso_clock_gettime (5 samples, 1.52%)[[vdso]] (2 samples, 0.61%)core::ops::function::FnOnce::call_once (12 samples, 3.65%)core..tftp::instant_callback::{{closure}} (11 samples, 3.34%)tft..std::time::SystemTime::now (2 samples, 0.61%)std::sys::unix::time::inner::<impl std::sys::unix::time::SystemTime>::now (2 samples, 0.61%)tftp::instant_callback (17 samples, 5.17%)tftp::..tftp::std_compat::time::Instant::from_time (15 samples, 4.56%)tftp:..core::time::Duration::from_micros (3 samples, 0.91%)core::time::Duration::new (1 samples, 0.30%)tftp::packet::PacketType::from_repr (1 samples, 0.30%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.30%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.61%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.61%)core::result::Result<T,E>::map (1 samples, 0.30%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (4 samples, 1.22%)core::option::Option<T>::ok_or (5 samples, 1.52%)core::ptr::drop_in_place<tftp::error::PacketError> (2 samples, 0.61%)tftp::packet::PacketType::from_bytes (14 samples, 4.26%)tftp:..tftp::packet::try_from (13 samples, 3.95%)tftp..core::slice::<impl [T]>::get (1 samples, 0.30%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.30%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.30%)all (329 samples, 100%)tftp (329 samples, 100.00%)tftp[unknown] (322 samples, 97.87%)[unknown]tftp::client::client::receive_file (312 samples, 94.83%)tftp::client::client::receive_filetftp::std_compat::time::Instant::elapsed (2 samples, 0.61%)core::ops::function::FnOnce::call_once (1 samples, 0.30%)tftp::instant_callback::{{closure}} (1 samples, 0.30%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.30%)clock_gettime (1 samples, 0.30%)__vdso_clock_gettime (1 samples, 0.30%) \ No newline at end of file diff --git a/info/receiver_window_size_delayed_encryption.png b/info/receiver_window_size_delayed_encryption.png new file mode 100644 index 0000000..08e5b82 Binary files /dev/null and b/info/receiver_window_size_delayed_encryption.png differ diff --git a/info/receiver_window_size_delayed_encryption_stack.png b/info/receiver_window_size_delayed_encryption_stack.png new file mode 100644 index 0000000..cd2f1cf Binary files /dev/null and b/info/receiver_window_size_delayed_encryption_stack.png differ diff --git a/info/receiver_window_size_no_encryption_alloc.png b/info/receiver_window_size_no_encryption_alloc.png new file mode 100644 index 0000000..66a2029 Binary files /dev/null and b/info/receiver_window_size_no_encryption_alloc.png differ diff --git a/info/receiver_window_size_no_encryption_stack.png b/info/receiver_window_size_no_encryption_stack.png new file mode 100644 index 0000000..21c0f6e Binary files /dev/null and b/info/receiver_window_size_no_encryption_stack.png differ diff --git a/info/send_capture_delayed_encryption.pcap b/info/send_capture_delayed_encryption.pcap new file mode 100644 index 0000000..e44b7e0 Binary files /dev/null and b/info/send_capture_delayed_encryption.pcap differ diff --git a/info/send_capture_no_encryption_stack.pcap b/info/send_capture_no_encryption_stack.pcap new file mode 100644 index 0000000..f13f8d6 Binary files /dev/null and b/info/send_capture_no_encryption_stack.pcap differ diff --git a/info/send_flamegraph.svg b/info/send_flamegraph.svg new file mode 100644 index 0000000..76b059e --- /dev/null +++ b/info/send_flamegraph.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)[ld-linux-x86-64.so.2] (6 samples, 0.25%)[unknown] (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.12%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (108 samples, 4.50%)<tftp..core::iter::traits::iterator::Iterator::collect (108 samples, 4.50%)core:..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (108 samples, 4.50%)<allo..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (108 samples, 4.50%)<allo..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (108 samples, 4.50%)<allo..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (108 samples, 4.50%)<allo..alloc::vec::Vec<T,A>::extend_trusted (108 samples, 4.50%)alloc..core::iter::traits::iterator::Iterator::for_each (108 samples, 4.50%)core:..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (108 samples, 4.50%)<core..<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::fold (108 samples, 4.50%)<core..core::iter::traits::iterator::Iterator::fold (108 samples, 4.50%)core:..core::iter::adapters::copied::copy_fold::{{closure}} (50 samples, 2.08%)c..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (18 samples, 0.75%)core::ptr::const_ptr::<impl *const T>::add (4 samples, 0.17%)core::ptr::const_ptr::<impl *const T>::offset (2 samples, 0.08%)<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::next (52 samples, 2.17%)<..core::ptr::read (9 samples, 0.37%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.08%)alloc::vec::set_len_on_drop::SetLenOnDrop::current_len (5 samples, 0.21%)core::ptr::mut_ptr::<impl *mut T>::add (9 samples, 0.37%)core::ptr::mut_ptr::<impl *mut T>::offset (9 samples, 0.37%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (208 samples, 8.66%)<tftp::packe..core::iter::traits::iterator::Iterator::collect (100 samples, 4.16%)core:..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (100 samples, 4.16%)<allo..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (100 samples, 4.16%)<allo..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (100 samples, 4.16%)<allo..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (100 samples, 4.16%)<allo..alloc::vec::Vec<T,A>::extend_trusted (100 samples, 4.16%)alloc..core::iter::traits::iterator::Iterator::for_each (100 samples, 4.16%)core:..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (100 samples, 4.16%)<core..core::iter::traits::iterator::Iterator::fold (100 samples, 4.16%)core:..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (48 samples, 2.00%)c..alloc::vec::Vec<T,A>::extend_trusted::{{closure}} (48 samples, 2.00%)a..core::ptr::write (20 samples, 0.83%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (2 samples, 0.08%)tftp::encryption::Encryptor::decrypt (2 samples, 0.08%)aead::AeadInPlace::decrypt_in_place (2 samples, 0.08%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (2 samples, 0.08%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (1 samples, 0.04%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (1 samples, 0.04%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.04%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.04%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (1 samples, 0.04%)<[Z: N] as zeroize::Zeroize>::zeroize (1 samples, 0.04%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (1 samples, 0.04%)<Z as zeroize::Zeroize>::zeroize (1 samples, 0.04%)zeroize::atomic_fence (1 samples, 0.04%)core::sync::atomic::compiler_fence (1 samples, 0.04%)<alloc::vec::Vec<u8> as aead::Buffer>::extend_from_slice (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_from_slice (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<&T,core::slice::iter::Iter<T>>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::append_elements (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.04%)alloc::raw_vec::finish_grow (1 samples, 0.04%)core::result::Result<T,E>::map_err (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.08%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.08%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.08%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (5 samples, 0.21%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.17%)generic_array::ArrayBuilder<T,N>::into_inner (2 samples, 0.08%)core::ptr::read (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (7 samples, 0.29%)tftp::encryption::Encryptor::encrypt (7 samples, 0.29%)aead::AeadInPlace::encrypt_in_place (7 samples, 0.29%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (6 samples, 0.25%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::clone::Clone>::clone (1 samples, 0.04%)alloc::slice::<impl [T]>::to_vec_in (1 samples, 0.04%)alloc::slice::hack::to_vec (1 samples, 0.04%)<T as alloc::slice::hack::ConvertVec>::to_vec (1 samples, 0.04%)alloc::vec::Vec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::allocate_in (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.04%)alloc::alloc::Global::alloc_impl (1 samples, 0.04%)alloc::alloc::alloc (1 samples, 0.04%)malloc (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::set_ptr_and_cap (1 samples, 0.04%)core::cmp::max (1 samples, 0.04%)core::cmp::Ord::max (1 samples, 0.04%)core::cmp::max_by (1 samples, 0.04%)[libc.so.6] (221 samples, 9.20%)[libc.so.6]main (221 samples, 9.20%)mainstd::rt::lang_start (221 samples, 9.20%)std::rt::lang..std::rt::lang_start_internal (221 samples, 9.20%)std::rt::lang..std::panic::catch_unwind (221 samples, 9.20%)std::panic::c..std::panicking::try (221 samples, 9.20%)std::panickin..std::panicking::try::do_call (221 samples, 9.20%)std::panickin..std::rt::lang_start_internal::{{closure}} (221 samples, 9.20%)std::rt::lang..std::panic::catch_unwind (221 samples, 9.20%)std::panic::c..std::panicking::try (221 samples, 9.20%)std::panickin..std::panicking::try::do_call (221 samples, 9.20%)std::panickin..core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (221 samples, 9.20%)core::ops::fu..std::rt::lang_start::{{closure}} (221 samples, 9.20%)std::rt::lang..std::sys_common::backtrace::__rust_begin_short_backtrace (221 samples, 9.20%)std::sys_comm..core::ops::function::FnOnce::call_once (221 samples, 9.20%)core::ops::fu..tftp::main (221 samples, 9.20%)tftp::maintftp::start_send (221 samples, 9.20%)tftp::start_s..tftp::client::client::send_file (221 samples, 9.20%)tftp::client:..<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (4 samples, 0.17%)tftp::storage::FileReader<T>::read_block (3 samples, 0.12%)alloc::vec::Vec<T,A>::resize (3 samples, 0.12%)alloc::vec::Vec<T,A>::extend_with (3 samples, 0.12%)alloc::vec::Vec<T,A>::reserve (3 samples, 0.12%)alloc::raw_vec::RawVec<T,A>::reserve (3 samples, 0.12%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (3 samples, 0.12%)alloc::raw_vec::RawVec<T,A>::grow_amortized (3 samples, 0.12%)core::option::Option<T>::ok_or (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.08%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.08%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.08%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.08%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.08%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.08%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (3 samples, 0.12%)tftp::encryption::Encryptor::decrypt (3 samples, 0.12%)aead::AeadInPlace::decrypt_in_place (3 samples, 0.12%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (3 samples, 0.12%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (3 samples, 0.12%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.12%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.12%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)__libc_start_main (4 samples, 0.17%)[libc.so.6] (4 samples, 0.17%)main (4 samples, 0.17%)std::rt::lang_start (4 samples, 0.17%)std::rt::lang_start_internal (4 samples, 0.17%)std::panic::catch_unwind (4 samples, 0.17%)std::panicking::try (4 samples, 0.17%)std::panicking::try::do_call (4 samples, 0.17%)std::rt::lang_start_internal::{{closure}} (4 samples, 0.17%)std::panic::catch_unwind (4 samples, 0.17%)std::panicking::try (4 samples, 0.17%)std::panicking::try::do_call (4 samples, 0.17%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (4 samples, 0.17%)std::rt::lang_start::{{closure}} (4 samples, 0.17%)std::sys_common::backtrace::__rust_begin_short_backtrace (4 samples, 0.17%)core::ops::function::FnOnce::call_once (4 samples, 0.17%)tftp::main (4 samples, 0.17%)tftp::start_send (4 samples, 0.17%)tftp::client::client::send_file (4 samples, 0.17%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (1 samples, 0.04%)tftp::encryption::Encryptor::encrypt (1 samples, 0.04%)aead::AeadInPlace::encrypt_in_place (1 samples, 0.04%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)clap::derive::Parser::parse (1 samples, 0.04%)clap::builder::command::Command::get_matches (1 samples, 0.04%)clap::builder::command::Command::get_matches_from (1 samples, 0.04%)clap::builder::command::Command::try_get_matches_from_mut (1 samples, 0.04%)clap::builder::command::Command::_do_parse (1 samples, 0.04%)clap::builder::command::Command::_build_self (1 samples, 0.04%)clap::builder::debug_asserts::assert_app (1 samples, 0.04%)clap::builder::debug_asserts::_verify_positionals (1 samples, 0.04%)clap::builder::arg::Arg::is_trailing_var_arg_set (1 samples, 0.04%)clap::builder::arg::Arg::is_set (1 samples, 0.04%)alloc::vec::set_len_on_drop::SetLenOnDrop::current_len (5 samples, 0.21%)core::ptr::mut_ptr::<impl *mut T>::add (11 samples, 0.46%)core::ptr::mut_ptr::<impl *mut T>::offset (10 samples, 0.42%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (53 samples, 2.21%)<..<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (53 samples, 2.21%)<..core::iter::traits::iterator::Iterator::collect (53 samples, 2.21%)c..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (53 samples, 2.21%)<..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (53 samples, 2.21%)<..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (53 samples, 2.21%)<..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (53 samples, 2.21%)<..alloc::vec::Vec<T,A>::extend_trusted (53 samples, 2.21%)a..core::iter::traits::iterator::Iterator::for_each (53 samples, 2.21%)c..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (53 samples, 2.21%)<..<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::fold (53 samples, 2.21%)<..core::iter::traits::iterator::Iterator::fold (53 samples, 2.21%)c..core::iter::adapters::copied::copy_fold::{{closure}} (53 samples, 2.21%)c..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (53 samples, 2.21%)c..alloc::vec::Vec<T,A>::extend_trusted::{{closure}} (53 samples, 2.21%)a..core::ptr::write (22 samples, 0.92%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (2 samples, 0.08%)tftp::encryption::Encryptor::encrypt (2 samples, 0.08%)aead::AeadInPlace::encrypt_in_place (2 samples, 0.08%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (2 samples, 0.08%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (2 samples, 0.08%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (2 samples, 0.08%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (2 samples, 0.08%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.08%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.08%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.08%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.08%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::entry (1 samples, 0.04%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (1 samples, 0.04%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (1 samples, 0.04%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (1 samples, 0.04%)std::rt::lang_start (57 samples, 2.37%)st..std::rt::lang_start_internal (57 samples, 2.37%)st..std::panic::catch_unwind (57 samples, 2.37%)st..std::panicking::try (57 samples, 2.37%)st..std::panicking::try::do_call (57 samples, 2.37%)st..std::rt::lang_start_internal::{{closure}} (57 samples, 2.37%)st..std::panic::catch_unwind (57 samples, 2.37%)st..std::panicking::try (57 samples, 2.37%)st..std::panicking::try::do_call (57 samples, 2.37%)st..core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (57 samples, 2.37%)co..std::rt::lang_start::{{closure}} (57 samples, 2.37%)st..std::sys_common::backtrace::__rust_begin_short_backtrace (57 samples, 2.37%)st..core::ops::function::FnOnce::call_once (57 samples, 2.37%)co..tftp::main (57 samples, 2.37%)tf..tftp::start_send (57 samples, 2.37%)tf..tftp::client::client::send_file (57 samples, 2.37%)tf..<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (2 samples, 0.08%)tftp::storage::FileReader<T>::read_block (1 samples, 0.04%)alloc::vec::Vec<T,A>::resize (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_with (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.04%)core::num::<impl usize>::checked_add (1 samples, 0.04%)core::num::<impl usize>::overflowing_add (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::is_null (2 samples, 0.08%)core::ptr::mut_ptr::<impl *mut T>::is_null (10 samples, 0.42%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (3 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::addr (3 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::add (11 samples, 0.46%)core::ptr::mut_ptr::<impl *mut T>::offset (11 samples, 0.46%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (77 samples, 3.21%)<tf..core::iter::traits::iterator::Iterator::collect (77 samples, 3.21%)cor..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (77 samples, 3.21%)<al..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (77 samples, 3.21%)<al..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (77 samples, 3.21%)<al..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (77 samples, 3.21%)<al..alloc::vec::Vec<T,A>::extend_trusted (77 samples, 3.21%)all..core::iter::traits::iterator::Iterator::for_each (77 samples, 3.21%)cor..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (77 samples, 3.21%)<co..<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::fold (77 samples, 3.21%)<co..core::iter::traits::iterator::Iterator::fold (77 samples, 3.21%)cor..<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (77 samples, 3.21%)<co..core::slice::iter::Iter<T>::post_inc_start (41 samples, 1.71%)core::ptr::non_null::NonNull<T>::new_unchecked (6 samples, 0.25%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.04%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (1 samples, 0.04%)core::ops::function::Fn::call (1 samples, 0.04%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (1 samples, 0.04%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (1 samples, 0.04%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_trusted::{{closure}} (1 samples, 0.04%)<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.08%)core::ptr::const_ptr::<impl *const T>::sub_ptr (1 samples, 0.04%)alloc::vec::into_iter::IntoIter<T,A>::as_raw_mut_slice (3 samples, 0.12%)<&mut I as core::iter::traits::exact_size::ExactSizeIterator>::len (3 samples, 0.12%)core::iter::traits::exact_size::ExactSizeIterator::len (3 samples, 0.12%)<core::option::Option<T> as core::cmp::PartialEq>::eq (1 samples, 0.04%)<T as core::option::SpecOptionPartialEq>::eq (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialEq for usize>::eq (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (83 samples, 3.46%)<tf..core::iter::traits::iterator::Iterator::collect (6 samples, 0.25%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (6 samples, 0.25%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (6 samples, 0.25%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (6 samples, 0.25%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (6 samples, 0.25%)alloc::vec::Vec<T,A>::extend_trusted (6 samples, 0.25%)core::iter::traits::iterator::Iterator::for_each (6 samples, 0.25%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (6 samples, 0.25%)core::iter::traits::iterator::Iterator::fold (5 samples, 0.21%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u8>> (5 samples, 0.21%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (5 samples, 0.21%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u8,alloc::alloc::Global>> (2 samples, 0.08%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.08%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (2 samples, 0.08%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::current_memory (2 samples, 0.08%)core::alloc::layout::Layout::array (1 samples, 0.04%)core::ptr::alignment::Alignment::of (1 samples, 0.04%)core::ptr::alignment::Alignment::new_unchecked (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (1 samples, 0.04%)tftp::encryption::Encryptor::decrypt (1 samples, 0.04%)aead::AeadInPlace::decrypt_in_place (1 samples, 0.04%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)core::num::<impl u32>::from_le_bytes (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.12%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (3 samples, 0.12%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (8 samples, 0.33%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (7 samples, 0.29%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (7 samples, 0.29%)core::iter::traits::iterator::Iterator::for_each (7 samples, 0.29%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (7 samples, 0.29%)core::iter::traits::iterator::Iterator::fold (7 samples, 0.29%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.17%)core::slice::iter::IterMut<T>::post_inc_start (2 samples, 0.08%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.17%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.17%)<usize as core::iter::range::Step>::forward_unchecked (3 samples, 0.12%)<[Z] as zeroize::Zeroize>::zeroize (7 samples, 0.29%)zeroize::volatile_set (7 samples, 0.29%)core::ptr::write_volatile (2 samples, 0.08%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (8 samples, 0.33%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.04%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (9 samples, 0.37%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.04%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.04%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (1 samples, 0.04%)<[Z: N] as zeroize::Zeroize>::zeroize (1 samples, 0.04%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (1 samples, 0.04%)<Z as zeroize::Zeroize>::zeroize (1 samples, 0.04%)zeroize::atomic_fence (1 samples, 0.04%)core::sync::atomic::compiler_fence (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (18 samples, 0.75%)tftp::encryption::Encryptor::encrypt (18 samples, 0.75%)aead::AeadInPlace::encrypt_in_place (18 samples, 0.75%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (18 samples, 0.75%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (10 samples, 0.42%)universal_hash::UniversalHash::update_padded (1 samples, 0.04%)universal_hash::UniversalHash::update (1 samples, 0.04%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::free_block (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove_entry (1 samples, 0.04%)alloc::collections::btree::map::entry::OccupiedEntry<K,V,A>::remove_entry (1 samples, 0.04%)alloc::collections::btree::map::entry::OccupiedEntry<K,V,A>::remove_kv (1 samples, 0.04%)alloc::collections::btree::remove::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking (1 samples, 0.04%)alloc::collections::btree::remove::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv (1 samples, 0.04%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::KV>::remove (1 samples, 0.04%)alloc::collections::btree::node::slice_remove (1 samples, 0.04%)std::rt::lang_start_internal (104 samples, 4.33%)std::..std::panic::catch_unwind (104 samples, 4.33%)std::..std::panicking::try (104 samples, 4.33%)std::..std::panicking::try::do_call (104 samples, 4.33%)std::..std::rt::lang_start_internal::{{closure}} (104 samples, 4.33%)std::..std::panic::catch_unwind (104 samples, 4.33%)std::..std::panicking::try (104 samples, 4.33%)std::..std::panicking::try::do_call (104 samples, 4.33%)std::..core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (104 samples, 4.33%)core:..std::rt::lang_start::{{closure}} (104 samples, 4.33%)std::..std::sys_common::backtrace::__rust_begin_short_backtrace (104 samples, 4.33%)std::..core::ops::function::FnOnce::call_once (104 samples, 4.33%)core:..tftp::main (104 samples, 4.33%)tftp:..tftp::start_send (104 samples, 4.33%)tftp:..tftp::client::client::send_file (104 samples, 4.33%)tftp:..<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (1 samples, 0.04%)tftp::storage::FileReader<T>::read_block (1 samples, 0.04%)alloc::vec::Vec<T,A>::resize (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_with (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.04%)alloc::raw_vec::finish_grow (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (2 samples, 0.08%)<[Z] as zeroize::Zeroize>::zeroize (2 samples, 0.08%)zeroize::volatile_set (2 samples, 0.08%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.08%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.08%)core::mem::replace (2 samples, 0.08%)core::ptr::read (1 samples, 0.04%)std::sys_common::backtrace::__rust_begin_short_backtrace (3 samples, 0.12%)core::ops::function::FnOnce::call_once (3 samples, 0.12%)tftp::main (3 samples, 0.12%)tftp::start_send (3 samples, 0.12%)tftp::client::client::send_file (3 samples, 0.12%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (3 samples, 0.12%)tftp::encryption::Encryptor::encrypt (3 samples, 0.12%)aead::AeadInPlace::encrypt_in_place (3 samples, 0.12%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (3 samples, 0.12%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (3 samples, 0.12%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (3 samples, 0.12%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.04%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (1 samples, 0.04%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (1 samples, 0.04%)<[Z: N] as zeroize::Zeroize>::zeroize (1 samples, 0.04%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (1 samples, 0.04%)<&mut I as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (75 samples, 3.12%)cor..core::core_arch::x86::m128iExt::as_i32x4 (13 samples, 0.54%)core::core_arch::x86::sse2::_mm_slli_epi32 (47 samples, 1.96%)c..core::core_arch::x86::m128iExt::as_i32x4 (13 samples, 0.54%)core::core_arch::x86::sse2::_mm_srli_epi32 (16 samples, 0.67%)core::core_arch::x86::m128iExt::as_i32x4 (4 samples, 0.17%)chacha20::backends::sse2::add_xor_rot (352 samples, 14.66%)chacha20::backends::ss..core::core_arch::x86::sse2::_mm_xor_si128 (47 samples, 1.96%)c..chacha20::backends::sse2::cols_to_rows (23 samples, 0.96%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (16 samples, 0.67%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.08%)chacha20::backends::sse2::double_quarter_round (393 samples, 16.37%)chacha20::backends::sse2:..chacha20::backends::sse2::rows_to_cols (16 samples, 0.67%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (10 samples, 0.42%)core::core_arch::x86::m128iExt::as_i32x4 (4 samples, 0.17%)core::core_arch::x86::sse2::_mm_add_epi32 (4 samples, 0.17%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.08%)core::ptr::read (6 samples, 0.25%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (421 samples, 17.53%)<chacha20::backends::sse2::..chacha20::backends::sse2::rounds (421 samples, 17.53%)chacha20::backends::sse2::r..core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (16 samples, 0.67%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (15 samples, 0.62%)core::mem::replace (9 samples, 0.37%)core::ptr::write (1 samples, 0.04%)core::ptr::write (9 samples, 0.37%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (122 samples, 5.08%)<core:..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (88 samples, 3.67%)core..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (65 samples, 2.71%)<g..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (13 samples, 0.54%)<u8 as core::default::Default>::default (3 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::is_null (11 samples, 0.46%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (6 samples, 0.25%)core::ptr::mut_ptr::<impl *mut T>::addr (6 samples, 0.25%)core::ptr::mut_ptr::<impl *mut T>::add (7 samples, 0.29%)core::ptr::mut_ptr::<impl *mut T>::offset (6 samples, 0.25%)core::ptr::non_null::NonNull<T>::as_ptr (3 samples, 0.12%)core::iter::traits::iterator::Iterator::for_each (233 samples, 9.70%)core::iter::tr..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (232 samples, 9.66%)<core::iter::a..core::iter::traits::iterator::Iterator::fold (232 samples, 9.66%)core::iter::tr..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (67 samples, 2.79%)<c..core::slice::iter::IterMut<T>::post_inc_start (41 samples, 1.71%)core::ptr::non_null::NonNull<T>::new_unchecked (4 samples, 0.17%)[libc.so.6] (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (5 samples, 0.21%)core::ptr::read (4 samples, 0.17%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.08%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)memcpy (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (240 samples, 10.00%)generic_array:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (240 samples, 10.00%)<generic_array..generic_array::ArrayBuilder<T,N>::new (1 samples, 0.04%)memcpy (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::ptr::read (2 samples, 0.08%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::ptr::write (10 samples, 0.42%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (137 samples, 5.71%)<core::..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (100 samples, 4.16%)core:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (79 samples, 3.29%)<ge..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (13 samples, 0.54%)<u8 as core::default::Default>::default (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (15 samples, 0.62%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (5 samples, 0.21%)core::ptr::mut_ptr::<impl *mut T>::addr (4 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::add (8 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::offset (8 samples, 0.33%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (259 samples, 10.79%)core::iter::trai..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (259 samples, 10.79%)<core::iter::ada..core::iter::traits::iterator::Iterator::fold (257 samples, 10.70%)core::iter::trai..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (71 samples, 2.96%)<co..core::slice::iter::IterMut<T>::post_inc_start (39 samples, 1.62%)core::ptr::non_null::NonNull<T>::new_unchecked (2 samples, 0.08%)core::mem::forget (1 samples, 0.04%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)[libc.so.6] (2 samples, 0.08%)generic_array::ArrayBuilder<T,N>::into_inner (8 samples, 0.33%)core::ptr::read (3 samples, 0.12%)memcpy (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (936 samples, 38.98%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detachedcipher::stream::StreamCipher::apply_keystream (936 samples, 38.98%)cipher::stream::StreamCipher::apply_keystreamcipher::stream::StreamCipher::try_apply_keystream (936 samples, 38.98%)cipher::stream::StreamCipher::try_apply_keystream<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (936 samples, 38.98%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::s..cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (936 samples, 38.98%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_in..<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (936 samples, 38.98%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::Strea..<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (936 samples, 38.98%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCor..chacha20::backends::sse2::inner (936 samples, 38.98%)chacha20::backends::sse2::inner<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (936 samples, 38.98%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core:..inout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (275 samples, 11.45%)inout::inout::InO..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (273 samples, 11.37%)generic_array::im..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (273 samples, 11.37%)<generic_array::G..generic_array::ArrayBuilder<T,N>::iter_position (5 samples, 0.21%)core::slice::<impl [T]>::iter_mut (3 samples, 0.12%)core::slice::iter::IterMut<T>::new (3 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_cvtsi128_si32 (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (2 samples, 0.08%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.08%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.08%)chacha20::backends::sse2::inner (2 samples, 0.08%)core::core_arch::x86::sse2::_mm_loadu_si128 (1 samples, 0.04%)core::intrinsics::copy_nonoverlapping (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_slli_epi32 (2 samples, 0.08%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)tftp::client::client::send_file (955 samples, 39.78%)tftp::client::client::send_file<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (955 samples, 39.78%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>:..tftp::encryption::Encryptor::encrypt (955 samples, 39.78%)tftp::encryption::Encryptor::encryptaead::AeadInPlace::encrypt_in_place (955 samples, 39.78%)aead::AeadInPlace::encrypt_in_place<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (955 samples, 39.78%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::enc..chacha20poly1305::cipher::Cipher<C>::new (19 samples, 0.79%)cipher::stream::StreamCipher::apply_keystream (19 samples, 0.79%)cipher::stream::StreamCipher::try_apply_keystream (19 samples, 0.79%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (19 samples, 0.79%)cipher::stream_core::StreamCipherCore::write_keystream_block (17 samples, 0.71%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (17 samples, 0.71%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (17 samples, 0.71%)chacha20::backends::sse2::inner (17 samples, 0.71%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (17 samples, 0.71%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (17 samples, 0.71%)chacha20::backends::sse2::rounds (17 samples, 0.71%)chacha20::backends::sse2::double_quarter_round (17 samples, 0.71%)chacha20::backends::sse2::add_xor_rot (17 samples, 0.71%)core::core_arch::x86::sse2::_mm_xor_si128 (2 samples, 0.08%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)chacha20::xchacha::hchacha (1 samples, 0.04%)chacha20::xchacha::quarter_round (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1 samples, 0.04%)cipher::stream::StreamCipher::try_apply_keystream (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1 samples, 0.04%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.04%)core::result::Result<T,E>::ok (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)universal_hash::UniversalHash::update_padded (2 samples, 0.08%)universal_hash::UniversalHash::update (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.04%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.04%)poly1305::backend::soft::State::compute_block (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (4 samples, 0.17%)universal_hash::UniversalHash::verify (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (1 samples, 0.04%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (1 samples, 0.04%)poly1305::backend::soft::State::finalize_mut (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<[Z] as zeroize::Zeroize>::zeroize (1 samples, 0.04%)zeroize::volatile_set (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (7 samples, 0.29%)tftp::encryption::Encryptor::decrypt (7 samples, 0.29%)aead::AeadInPlace::decrypt_in_place (7 samples, 0.29%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (7 samples, 0.29%)chacha20poly1305::cipher::Cipher<C>::new (2 samples, 0.08%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)<alloc::vec::Vec<u8> as aead::Buffer>::extend_from_slice (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_from_slice (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<&T,core::slice::iter::Iter<T>>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::append_elements (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.04%)alloc::raw_vec::finish_grow (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::grow (1 samples, 0.04%)alloc::alloc::Global::grow_impl (1 samples, 0.04%)alloc::alloc::realloc (1 samples, 0.04%)__rust_realloc (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (5 samples, 0.21%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (4 samples, 0.17%)core::result::Result<T,E>::map (3 samples, 0.12%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.04%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.04%)core::slice::raw::from_raw_parts (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)core::num::<impl u32>::from_le_bytes (1 samples, 0.04%)core::num::<impl u32>::from_ne_bytes (1 samples, 0.04%)core::slice::<impl [T]>::chunks_exact (1 samples, 0.04%)core::slice::iter::ChunksExact<T>::new (1 samples, 0.04%)core::slice::<impl [T]>::split_at_unchecked (1 samples, 0.04%)core::slice::raw::from_raw_parts (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (9 samples, 0.37%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (2 samples, 0.08%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.12%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (3 samples, 0.12%)core::result::Result<T,E>::map (3 samples, 0.12%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.17%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (2 samples, 0.08%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.04%)core::num::<impl u32>::rotate_left (3 samples, 0.12%)chacha20::xchacha::quarter_round (24 samples, 1.00%)core::num::<impl u32>::wrapping_add (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.08%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.08%)core::mem::replace (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::cmp::min (1 samples, 0.04%)core::cmp::Ord::min (1 samples, 0.04%)core::cmp::min_by (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (2 samples, 0.08%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.04%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)core::iter::traits::iterator::Iterator::zip (5 samples, 0.21%)core::iter::adapters::zip::Zip<A,B>::new (3 samples, 0.12%)[libc.so.6] (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (8 samples, 0.33%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (6 samples, 0.25%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (5 samples, 0.21%)core::iter::traits::iterator::Iterator::for_each (11 samples, 0.46%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (11 samples, 0.46%)core::iter::traits::iterator::Iterator::fold (11 samples, 0.46%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.12%)core::slice::iter::IterMut<T>::post_inc_start (2 samples, 0.08%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (64 samples, 2.67%)<c..<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (64 samples, 2.67%)<c..chacha20::xchacha::hchacha (55 samples, 2.29%)c..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (14 samples, 0.58%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (14 samples, 0.58%)generic_array::ArrayBuilder<T,N>::into_inner (2 samples, 0.08%)core::mem::forget (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.12%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (3 samples, 0.12%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (3 samples, 0.12%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (6 samples, 0.25%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (6 samples, 0.25%)poly1305::backend::soft::State::finalize_mut (6 samples, 0.25%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.17%)core::iter::traits::iterator::Iterator::for_each (4 samples, 0.17%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.17%)core::iter::traits::iterator::Iterator::fold (4 samples, 0.17%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.17%)core::iter::traits::iterator::Iterator::for_each (4 samples, 0.17%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.17%)core::iter::traits::iterator::Iterator::fold (4 samples, 0.17%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)core::result::Result<T,E>::unwrap (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (8 samples, 0.33%)universal_hash::UniversalHash::update (4 samples, 0.17%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (4 samples, 0.17%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (4 samples, 0.17%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (4 samples, 0.17%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (4 samples, 0.17%)poly1305::backend::soft::State::compute_block (4 samples, 0.17%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (8 samples, 0.33%)cipher::stream::StreamCipher::try_apply_keystream (8 samples, 0.33%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (8 samples, 0.33%)inout::inout_buf::InOutBuf<u8>::xor_in2out (8 samples, 0.33%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.21%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.21%)core::mem::replace (3 samples, 0.12%)core::ptr::read (1 samples, 0.04%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.12%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.12%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.12%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.12%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.12%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.12%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.12%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (10 samples, 0.42%)<T as core::convert::TryInto<U>>::try_into (75 samples, 3.12%)<T ..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (56 samples, 2.33%)c..core::result::Result<T,E>::map (37 samples, 1.54%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (5 samples, 0.21%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (9 samples, 0.37%)core::slice::raw::from_raw_parts (6 samples, 0.25%)core::ptr::slice_from_raw_parts (4 samples, 0.17%)core::ptr::metadata::from_raw_parts (3 samples, 0.12%)core::convert::num::<impl core::convert::From<u32> for u64>::from (3 samples, 0.12%)core::num::<impl u32>::from_le_bytes (12 samples, 0.50%)core::num::<impl u32>::from_ne_bytes (2 samples, 0.08%)core::result::Result<T,E>::unwrap (14 samples, 0.58%)core::ptr::const_ptr::<impl *const T>::add (6 samples, 0.25%)core::ptr::const_ptr::<impl *const T>::offset (2 samples, 0.08%)core::ptr::const_ptr::<impl *const T>::cast (2 samples, 0.08%)universal_hash::UniversalHash::update (226 samples, 9.41%)universal_has..<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (226 samples, 9.41%)<poly1305::Po..<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (226 samples, 9.41%)<poly1305::ba..<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (225 samples, 9.37%)<universal_ha..<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (220 samples, 9.16%)<poly1305::ba..poly1305::backend::soft::State::compute_block (220 samples, 9.16%)poly1305::bac..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (39 samples, 1.62%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (35 samples, 1.46%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (25 samples, 1.04%)core::ptr::slice_from_raw_parts (7 samples, 0.29%)core::ptr::metadata::from_raw_parts (5 samples, 0.21%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (252 samples, 10.50%)chacha20poly130..universal_hash::UniversalHash::update_padded (230 samples, 9.58%)universal_hash..universal_hash::to_blocks (1 samples, 0.04%)core::slice::<impl [T]>::split_at (1 samples, 0.04%)core::slice::<impl [T]>::split_at_unchecked (1 samples, 0.04%)core::slice::raw::from_raw_parts (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)<[Z] as zeroize::Zeroize>::zeroize (4 samples, 0.17%)zeroize::volatile_set (4 samples, 0.17%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.08%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (3 samples, 0.12%)cipher::stream::StreamCipher::try_apply_keystream (3 samples, 0.12%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (3 samples, 0.12%)inout::inout_buf::InOutBuf<u8>::xor_in2out (2 samples, 0.08%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)cipher::stream::StreamCipherSeek::seek (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipherSeek>::try_seek (1 samples, 0.04%)<u64 as cipher::stream::SeekNum>::into_block_byte (1 samples, 0.04%)generic_array::GenericArray<T,N>::from_slice (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.08%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.08%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.08%)core::ptr::write (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (5 samples, 0.21%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (5 samples, 0.21%)core::iter::traits::iterator::Iterator::fold (5 samples, 0.21%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (333 samples, 13.87%)<tftp::socket::Encryp..tftp::encryption::Encryptor::encrypt (333 samples, 13.87%)tftp::encryption::Enc..aead::AeadInPlace::encrypt_in_place (333 samples, 13.87%)aead::AeadInPlace::en..<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (332 samples, 13.83%)<chacha20poly1305::Ch..chacha20poly1305::cipher::Cipher<C>::new (16 samples, 0.67%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (6 samples, 0.25%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (6 samples, 0.25%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,Type>::key_area_mut (1 samples, 0.04%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,Type>::as_leaf_mut (1 samples, 0.04%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,Type>::val_area_mut (2 samples, 0.08%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (7 samples, 0.29%)alloc::collections::btree::map::entry::VacantEntry<K,V,A>::insert (7 samples, 0.29%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::insert_recursing (7 samples, 0.29%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::insert (6 samples, 0.25%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::insert_fit (6 samples, 0.25%)alloc::collections::btree::node::slice_insert (2 samples, 0.08%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)tftp::main (349 samples, 14.54%)tftp::maintftp::start_send (349 samples, 14.54%)tftp::start_sendtftp::client::client::send_file (349 samples, 14.54%)tftp::client::client::..<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (9 samples, 0.37%)tftp::storage::FileReader<T>::read_block (2 samples, 0.08%)alloc::vec::Vec<T,A>::resize (2 samples, 0.08%)alloc::vec::Vec<T,A>::extend_with (2 samples, 0.08%)alloc::vec::Vec<T,A>::reserve (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::reserve (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::grow_amortized (2 samples, 0.08%)alloc::raw_vec::finish_grow (2 samples, 0.08%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (2 samples, 0.08%)alloc::alloc::Global::alloc_impl (2 samples, 0.08%)alloc::alloc::alloc (2 samples, 0.08%)malloc (2 samples, 0.08%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1 samples, 0.04%)cipher::stream::StreamCipher::try_apply_keystream (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)chacha20::backends::sse2::inner (1 samples, 0.04%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (1 samples, 0.04%)chacha20::backends::sse2::rounds (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (1 samples, 0.04%)chacha20::backends::sse2::add_xor_rot (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_slli_epi32 (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (2 samples, 0.08%)tftp::encryption::Encryptor::decrypt (2 samples, 0.08%)aead::AeadInPlace::decrypt_in_place (2 samples, 0.08%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (2 samples, 0.08%)chacha20poly1305::cipher::Cipher<C>::new (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1 samples, 0.04%)cipher::stream::StreamCipher::try_apply_keystream (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)chacha20::backends::sse2::inner (1 samples, 0.04%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (1 samples, 0.04%)chacha20::backends::sse2::rounds (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (1 samples, 0.04%)chacha20::backends::sse2::add_xor_rot (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_set_epi32 (2 samples, 0.08%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)core::ptr::read (2 samples, 0.08%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (8 samples, 0.33%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (8 samples, 0.33%)core::mem::replace (4 samples, 0.17%)core::ptr::write (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (18 samples, 0.75%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.08%)core::ptr::mut_ptr::<impl *mut T>::offset (2 samples, 0.08%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (57 samples, 2.37%)<g..core::slice::raw::from_raw_parts (47 samples, 1.96%)c..core::ptr::slice_from_raw_parts (37 samples, 1.54%)core::ptr::metadata::from_raw_parts (35 samples, 1.46%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (18 samples, 0.75%)core::slice::raw::from_raw_parts_mut (10 samples, 0.42%)core::ptr::slice_from_raw_parts_mut (7 samples, 0.29%)core::ptr::metadata::from_raw_parts_mut (6 samples, 0.25%)<usize as core::iter::range::Step>::forward_unchecked (7 samples, 0.29%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (6 samples, 0.25%)core::ptr::read (28 samples, 1.17%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.12%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (3 samples, 0.12%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (87 samples, 3.62%)core..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (84 samples, 3.50%)<co..core::mem::replace (44 samples, 1.83%)c..core::ptr::write (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (299 samples, 12.45%)cipher::stream_core..<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (299 samples, 12.45%)<chacha20::xchacha:..<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (299 samples, 12.45%)<chacha20::ChaChaCo..chacha20::backends::sse2::inner (299 samples, 12.45%)chacha20::backends:..<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (298 samples, 12.41%)<cipher::stream_cor..inout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (278 samples, 11.58%)inout::inout::InO..core::ptr::write (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (6 samples, 0.25%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_slli_epi32 (3 samples, 0.12%)chacha20::backends::sse2::add_xor_rot (14 samples, 0.58%)core::core_arch::x86::sse2::_mm_srli_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (16 samples, 0.67%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (316 samples, 13.16%)chacha20poly1305::ci..cipher::stream::StreamCipher::apply_keystream (316 samples, 13.16%)cipher::stream::Stre..cipher::stream::StreamCipher::try_apply_keystream (316 samples, 13.16%)cipher::stream::Stre..<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (316 samples, 13.16%)<cipher::stream_wrap..cipher::stream_core::StreamCipherCore::write_keystream_block (17 samples, 0.71%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (17 samples, 0.71%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (17 samples, 0.71%)chacha20::backends::sse2::inner (17 samples, 0.71%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (17 samples, 0.71%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (17 samples, 0.71%)chacha20::backends::sse2::rounds (17 samples, 0.71%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)poly1305::backend::autodetect::avx2_cpuid::init_get (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (4 samples, 0.17%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (3 samples, 0.12%)core::result::Result<T,E>::map (1 samples, 0.04%)<poly1305::backend::soft::State as core::default::Default>::default (1 samples, 0.04%)core::array::<impl core::default::Default for [T: _]>::default (1 samples, 0.04%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (10 samples, 0.42%)poly1305::backend::autodetect::State::new (10 samples, 0.42%)poly1305::backend::soft::State::new (9 samples, 0.37%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::cast (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (1 samples, 0.04%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)chacha20::backends::sse2::rounds (2 samples, 0.08%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)[unknown] (2,027 samples, 84.42%)[unknown]tftp::start_send (333 samples, 13.87%)tftp::start_sendtftp::client::client::send_file (333 samples, 13.87%)tftp::client::client:..<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (331 samples, 13.79%)<tftp::socket::Encryp..tftp::encryption::Encryptor::encrypt (331 samples, 13.79%)tftp::encryption::Enc..aead::AeadInPlace::encrypt_in_place (331 samples, 13.79%)aead::AeadInPlace::en..<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (331 samples, 13.79%)<chacha20poly1305::Ch..chacha20poly1305::cipher::Cipher<C>::new (15 samples, 0.62%)cipher::stream::StreamCipher::apply_keystream (5 samples, 0.21%)cipher::stream::StreamCipher::try_apply_keystream (5 samples, 0.21%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (5 samples, 0.21%)cipher::stream_core::StreamCipherCore::write_keystream_block (5 samples, 0.21%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.21%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.21%)chacha20::backends::sse2::inner (4 samples, 0.17%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (3 samples, 0.12%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (3 samples, 0.12%)core::core_arch::x86::sse2::_mm_storeu_si128 (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (1 samples, 0.04%)core::mem::size_of_val (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::new (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 0.08%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (2 samples, 0.08%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (2 samples, 0.08%)alloc::vec::Vec<T>::with_capacity (1 samples, 0.04%)alloc::vec::Vec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::allocate_in (1 samples, 0.04%)core::iter::traits::iterator::Iterator::collect (3 samples, 0.12%)memcpy (1 samples, 0.04%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (6 samples, 0.25%)core::slice::<impl [T]>::iter (1 samples, 0.04%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.12%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (103 samples, 4.29%)<allo..alloc::vec::Vec<T,A>::extend_trusted (103 samples, 4.29%)alloc..core::iter::traits::iterator::Iterator::for_each (101 samples, 4.21%)core:..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (101 samples, 4.21%)<core..core::iter::traits::iterator::Iterator::fold (100 samples, 4.16%)core:..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (30 samples, 1.25%)core::iter::traits::iterator::Iterator::collect (105 samples, 4.37%)core:..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (105 samples, 4.37%)<allo..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (105 samples, 4.37%)<allo..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (105 samples, 4.37%)<allo..alloc::vec::Vec<T>::with_capacity (1 samples, 0.04%)alloc::vec::Vec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::allocate_in (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.04%)alloc::alloc::Global::alloc_impl (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (114 samples, 4.75%)<tftp:..tftp::packet::PacketType::to_bytes (1 samples, 0.04%)memcpy (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_desugared (1 samples, 0.04%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::iter::traits::iterator::Iterator::find (1 samples, 0.04%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.04%)<core::ops::control_flow::ControlFlow<B,C> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)polling::Poller::wait (8 samples, 0.33%)polling::epoll::Poller::wait (7 samples, 0.29%)epoll_wait (4 samples, 0.17%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (11 samples, 0.46%)std::net::udp::UdpSocket::recv_from (2 samples, 0.08%)std::sys_common::net::UdpSocket::recv_from (2 samples, 0.08%)std::sys::unix::net::Socket::recv_from (2 samples, 0.08%)std::sys::unix::net::Socket::recv_from_with_flags (2 samples, 0.08%)recvfrom (2 samples, 0.08%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (2 samples, 0.08%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (2 samples, 0.08%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (15 samples, 0.62%)tftp::encryption::Encryptor::decrypt (4 samples, 0.17%)aead::AeadInPlace::decrypt_in_place (4 samples, 0.17%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (2 samples, 0.08%)core::convert::num::<impl core::convert::From<u8> for usize>::from (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (1 samples, 0.04%)<core::option::IntoIter<A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::option::Item<A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::option::Option<T>::take (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (5 samples, 0.21%)std::net::udp::UdpSocket::send_to (3 samples, 0.12%)std::sys_common::net::UdpSocket::send_to (1 samples, 0.04%)log::max_level (2 samples, 0.08%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::reserve (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::grow_amortized (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.04%)core::alloc::layout::Layout::array (1 samples, 0.04%)core::alloc::layout::Layout::array::inner (1 samples, 0.04%)<alloc::vec::Vec<u8> as aead::Buffer>::extend_from_slice (3 samples, 0.12%)alloc::vec::Vec<T,A>::extend_from_slice (3 samples, 0.12%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<&T,core::slice::iter::Iter<T>>>::spec_extend (3 samples, 0.12%)alloc::vec::Vec<T,A>::append_elements (3 samples, 0.12%)core::intrinsics::copy_nonoverlapping (1 samples, 0.04%)memcpy (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (2 samples, 0.08%)core::slice::raw::from_raw_parts (2 samples, 0.08%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (5 samples, 0.21%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)tftp::encryption::Encryptor::encrypt (10 samples, 0.42%)aead::AeadInPlace::encrypt_in_place (10 samples, 0.42%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (7 samples, 0.29%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (7 samples, 0.29%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.04%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (21 samples, 0.87%)tftp::packet::PacketType::from_bytes (3 samples, 0.12%)tftp::packet::try_from (2 samples, 0.08%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove_entry (1 samples, 0.04%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (1 samples, 0.04%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (1 samples, 0.04%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (1 samples, 0.04%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut,K,V,Type>::keys (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::RangeInclusive<A>>::next (1 samples, 0.04%)<core::ops::range::RangeInclusive<T> as core::iter::range::RangeInclusiveIteratorImpl>::spec_next (1 samples, 0.04%)core::mem::replace (1 samples, 0.04%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::free_block (4 samples, 0.17%)core::option::Option<T>::map (2 samples, 0.08%)[libc.so.6] (2 samples, 0.08%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (1 samples, 0.04%)alloc::vec::Vec<T,A>::with_capacity_in (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::allocate_in (2 samples, 0.08%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (2 samples, 0.08%)alloc::alloc::Global::alloc_impl (2 samples, 0.08%)alloc::alloc::alloc (2 samples, 0.08%)malloc (2 samples, 0.08%)<alloc::vec::Vec<T,A> as core::clone::Clone>::clone (4 samples, 0.17%)alloc::slice::<impl [T]>::to_vec_in (3 samples, 0.12%)alloc::slice::hack::to_vec (3 samples, 0.12%)<T as alloc::slice::hack::ConvertVec>::to_vec (3 samples, 0.12%)core::ptr::const_ptr::<impl *const T>::copy_to_nonoverlapping (1 samples, 0.04%)core::intrinsics::copy_nonoverlapping (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::Edge>::new_edge (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::get_mut (3 samples, 0.12%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (2 samples, 0.08%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (2 samples, 0.08%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (2 samples, 0.08%)alloc::collections::btree::map::BTreeMap<K,V,A>::entry (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next::{{closure}} (1 samples, 0.04%)core::option::Option<T>::map (1 samples, 0.04%)std::time::Instant::elapsed (1 samples, 0.04%)tftp::instant_callback (1 samples, 0.04%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.04%)clock_gettime (1 samples, 0.04%)<alloc::vec::ExtendElement<T> as alloc::vec::ExtendWith<T>>::next (3 samples, 0.12%)alloc::vec::Vec<T,A>::reserve (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::reserve (2 samples, 0.08%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (2 samples, 0.08%)alloc::raw_vec::handle_reserve (2 samples, 0.08%)core::result::Result<T,E>::map_err (1 samples, 0.04%)alloc::vec::set_len_on_drop::SetLenOnDrop::increment_len (2 samples, 0.08%)<usize as core::iter::range::Step>::forward_unchecked (16 samples, 0.67%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (7 samples, 0.29%)core::ptr::read (31 samples, 1.29%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (5 samples, 0.21%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (5 samples, 0.21%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (107 samples, 4.46%)core:..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (101 samples, 4.21%)<core..core::mem::replace (45 samples, 1.87%)c..core::ptr::write (5 samples, 0.21%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (171 samples, 7.12%)<tftp::sto..tftp::storage::FileReader<T>::read_block (158 samples, 6.58%)tftp::sto..alloc::vec::Vec<T,A>::resize (158 samples, 6.58%)alloc::ve..alloc::vec::Vec<T,A>::extend_with (158 samples, 6.58%)alloc::ve..core::ptr::write (10 samples, 0.42%)<alloc::vec::ExtendElement<T> as alloc::vec::ExtendWith<T>>::next (2 samples, 0.08%)<usize as core::iter::range::Step>::forward_unchecked (4 samples, 0.17%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (12 samples, 0.50%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (12 samples, 0.50%)core::mem::replace (6 samples, 0.25%)core::ptr::read (5 samples, 0.21%)alloc::vec::Vec<T,A>::resize (24 samples, 1.00%)alloc::vec::Vec<T,A>::extend_with (24 samples, 1.00%)core::ptr::write (3 samples, 0.12%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.04%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (4 samples, 0.17%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (2 samples, 0.08%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.08%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (2 samples, 0.08%)alloc::alloc::dealloc (1 samples, 0.04%)cfree (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.04%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.04%)std::io::error::repr_bitpacked::Repr::data (2 samples, 0.08%)std::io::error::repr_bitpacked::decode_repr (2 samples, 0.08%)std::io::error::Error::kind (3 samples, 0.12%)std::sys::unix::decode_error_kind (1 samples, 0.04%)std::time::Instant::elapsed (3 samples, 0.12%)std::time::Instant::now (1 samples, 0.04%)std::sys::unix::time::inner::Instant::now (1 samples, 0.04%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.04%)clock_gettime (1 samples, 0.04%)tftp::flow_control::RateControl::start_rtt (1 samples, 0.04%)core::time::Duration::as_secs (1 samples, 0.04%)all (2,401 samples, 100%)tftp (2,401 samples, 100.00%)tftp_start (368 samples, 15.33%)_start__libc_start_main (368 samples, 15.33%)__libc_start_main[libc.so.6] (368 samples, 15.33%)[libc.so.6]main (368 samples, 15.33%)mainstd::rt::lang_start (368 samples, 15.33%)std::rt::lang_startstd::rt::lang_start_internal (368 samples, 15.33%)std::rt::lang_start_int..std::panic::catch_unwind (368 samples, 15.33%)std::panic::catch_unwindstd::panicking::try (368 samples, 15.33%)std::panicking::trystd::panicking::try::do_call (368 samples, 15.33%)std::panicking::try::do..std::rt::lang_start_internal::{{closure}} (368 samples, 15.33%)std::rt::lang_start_int..std::panic::catch_unwind (368 samples, 15.33%)std::panic::catch_unwindstd::panicking::try (368 samples, 15.33%)std::panicking::trystd::panicking::try::do_call (368 samples, 15.33%)std::panicking::try::do..core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (368 samples, 15.33%)core::ops::function::im..std::rt::lang_start::{{closure}} (368 samples, 15.33%)std::rt::lang_start::{{..std::sys_common::backtrace::__rust_begin_short_backtrace (368 samples, 15.33%)std::sys_common::backtr..core::ops::function::FnOnce::call_once (368 samples, 15.33%)core::ops::function::Fn..tftp::main (368 samples, 15.33%)tftp::maintftp::start_send (368 samples, 15.33%)tftp::start_sendtftp::client::client::send_file (368 samples, 15.33%)tftp::client::client::s..tftp::packet::PacketType::from_bytes (1 samples, 0.04%)tftp::packet::try_from (1 samples, 0.04%)core::slice::<impl [T]>::get (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%) \ No newline at end of file diff --git a/info/send_flamegraph_delayed_encryption_stack.svg b/info/send_flamegraph_delayed_encryption_stack.svg new file mode 100644 index 0000000..6993c18 --- /dev/null +++ b/info/send_flamegraph_delayed_encryption_stack.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (6 samples, 0.17%)[unknown] (1 samples, 0.03%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (5 samples, 0.14%)core::ops::function::FnOnce::call_once (2 samples, 0.06%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)<core::ops::index_range::IndexRange as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)<&mut I as core::iter::traits::exact_size::ExactSizeIterator>::len (1 samples, 0.03%)<core::ops::index_range::IndexRange as core::iter::traits::exact_size::ExactSizeIterator>::len (1 samples, 0.03%)core::ops::index_range::IndexRange::len (1 samples, 0.03%)core::iter::adapters::chain::and_then_or_clear (22 samples, 0.63%)core::option::Option<T>::as_mut (4 samples, 0.11%)core::ptr::const_ptr::<impl *const T>::is_null (18 samples, 0.51%)core::ptr::const_ptr::<impl *const T>::is_null::runtime_impl (6 samples, 0.17%)core::ptr::const_ptr::<impl *const T>::addr (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (18 samples, 0.51%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (7 samples, 0.20%)core::ptr::mut_ptr::<impl *mut T>::addr (5 samples, 0.14%)core::ptr::non_null::NonNull<T>::as_ptr (2 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::add (13 samples, 0.37%)core::ptr::mut_ptr::<impl *mut T>::offset (13 samples, 0.37%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (102 samples, 2.90%)<c..core::slice::iter::Iter<T>::post_inc_start (43 samples, 1.22%)core::ptr::non_null::NonNull<T>::new_unchecked (4 samples, 0.11%)<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::next (156 samples, 4.44%)<core..core::option::Option<&T>::copied (45 samples, 1.28%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (13 samples, 0.37%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (292 samples, 8.31%)<core::iter:..core::option::Option<T>::or_else (239 samples, 6.80%)core::opt..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next::{{closure}} (217 samples, 6.18%)<core::i..core::option::Option<T>::as_mut (7 samples, 0.20%)core::option::Option<T>::expect (22 samples, 0.63%)core::ptr::drop_in_place<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>>> (1 samples, 0.03%)core::result::Result<T,E>::ok (32 samples, 0.91%)heapless::vec::Vec<T,_>::new (2 samples, 0.06%)[libc.so.6] (2 samples, 0.06%)heapless::vec::Vec<T,_>::capacity (12 samples, 0.34%)core::mem::maybe_uninit::MaybeUninit<T>::new (39 samples, 1.11%)core::ptr::mut_ptr::<impl *mut T>::add (7 samples, 0.20%)core::ptr::mut_ptr::<impl *mut T>::offset (5 samples, 0.14%)core::slice::<impl [T]>::get_unchecked_mut (37 samples, 1.05%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (21 samples, 0.60%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (2 samples, 0.06%)heapless::vec::Vec<T,_>::push (194 samples, 5.52%)heaples..heapless::vec::Vec<T,_>::push_unchecked (161 samples, 4.58%)heapl..heapless::vec::Vec<T,_>::is_full (23 samples, 0.65%)heapless::vec::Vec<T,_>::capacity (10 samples, 0.28%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (628 samples, 17.87%)<tftp::packet::DataPacket as..core::iter::traits::iterator::Iterator::collect (628 samples, 17.87%)core::iter::traits::iterator..<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (628 samples, 17.87%)<heapless::vec::Vec<T,_> as ..memcpy (1 samples, 0.03%)core::array::iter::<impl core::iter::traits::collect::IntoIterator for [T: N]>::into_iter (1 samples, 0.03%)core::mem::transmute_copy (1 samples, 0.03%)core::iter::traits::iterator::Iterator::chain (2 samples, 0.06%)[libc.so.6] (2 samples, 0.06%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (5 samples, 0.14%)core::iter::adapters::chain::and_then_or_clear (24 samples, 0.68%)core::option::Option<T>::as_mut (2 samples, 0.06%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (19 samples, 0.54%)core::ptr::const_ptr::<impl *const T>::cast (2 samples, 0.06%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (62 samples, 1.76%)heapless::vec::Vec<T,_>::as_slice (57 samples, 1.62%)core::slice::raw::from_raw_parts (52 samples, 1.48%)core::ptr::slice_from_raw_parts (39 samples, 1.11%)core::ptr::metadata::from_raw_parts (36 samples, 1.02%)core::ptr::const_ptr::<impl *const T>::read (39 samples, 1.11%)core::ptr::read (36 samples, 1.02%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.06%)<heapless::vec::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (186 samples, 5.29%)<heapl..core::slice::<impl [T]>::get_unchecked_mut (26 samples, 0.74%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (17 samples, 0.48%)core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (324 samples, 9.22%)<core::iter::..core::option::Option<T>::or_else (284 samples, 8.08%)core::optio..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next::{{closure}} (254 samples, 7.23%)<core::ite..core::option::Option<T>::as_mut (8 samples, 0.23%)[libc.so.6] (1 samples, 0.03%)core::option::Option<T>::expect (18 samples, 0.51%)core::ptr::drop_in_place<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,heapless::vec::IntoIter<u8,1420_usize>>> (1 samples, 0.03%)core::ptr::drop_in_place<core::option::Option<heapless::vec::IntoIter<u8,1420_usize>>> (1 samples, 0.03%)core::ptr::drop_in_place<heapless::vec::IntoIter<u8,1420_usize>> (1 samples, 0.03%)<heapless::vec::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.03%)core::result::Result<T,E>::ok (28 samples, 0.80%)heapless::vec::Vec<T,_>::new (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)heapless::vec::Vec<T,_>::capacity (7 samples, 0.20%)core::mem::maybe_uninit::MaybeUninit<T>::new (38 samples, 1.08%)core::mem::manually_drop::ManuallyDrop<T>::new (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (6 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::offset (6 samples, 0.17%)core::slice::<impl [T]>::get_unchecked_mut (29 samples, 0.83%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (20 samples, 0.57%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (1 samples, 0.03%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (1,278 samples, 36.37%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_b..core::iter::traits::iterator::Iterator::collect (646 samples, 18.38%)core::iter::traits::iterator:..<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (646 samples, 18.38%)<heapless::vec::Vec<T,_> as c..heapless::vec::Vec<T,_>::push (187 samples, 5.32%)heaples..heapless::vec::Vec<T,_>::push_unchecked (151 samples, 4.30%)heapl..heapless::vec::Vec<T,_>::is_full (20 samples, 0.57%)heapless::vec::Vec<T,_>::capacity (8 samples, 0.23%)core::ptr::const_ptr::<impl *const T>::is_null (12 samples, 0.34%)core::ptr::const_ptr::<impl *const T>::is_null::runtime_impl (6 samples, 0.17%)core::ptr::const_ptr::<impl *const T>::addr (6 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::is_null (6 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (4 samples, 0.11%)core::ptr::mut_ptr::<impl *mut T>::addr (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::add (19 samples, 0.54%)core::ptr::mut_ptr::<impl *mut T>::offset (19 samples, 0.54%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (77 samples, 2.19%)<..core::slice::iter::Iter<T>::post_inc_start (44 samples, 1.25%)core::ptr::non_null::NonNull<T>::new_unchecked (5 samples, 0.14%)core::clone::impls::<impl core::clone::Clone for u8>::clone (5 samples, 0.14%)core::mem::maybe_uninit::MaybeUninit<T>::new (36 samples, 1.02%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::offset (2 samples, 0.06%)core::slice::<impl [T]>::get_unchecked_mut (20 samples, 0.57%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (13 samples, 0.37%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (2 samples, 0.06%)<heapless::vec::Vec<T,_> as core::clone::Clone>::clone (270 samples, 7.68%)<heapless::..heapless::vec::Vec<T,_>::clone (270 samples, 7.68%)heapless::v..heapless::vec::Vec<T,_>::push_unchecked (126 samples, 3.59%)heap..heapless::vec::Vec<T,_>::is_full (16 samples, 0.46%)heapless::vec::Vec<T,_>::capacity (4 samples, 0.11%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.03%)heapless::vec::Vec<T,_>::as_slice (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::is_finished (1 samples, 0.03%)tftp::map::Map<K,V,_>::is_empty (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::is_empty (1 samples, 0.03%)[libc.so.6] (2 samples, 0.06%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next::{{closure}}::{{closure}} (2 samples, 0.06%)[libc.so.6] (2 samples, 0.06%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next::{{closure}} (5 samples, 0.14%)core::option::Option<T>::map (5 samples, 0.14%)[libc.so.6] (3 samples, 0.09%)core::result::Result<T,E>::map (7 samples, 0.20%)[libc.so.6] (2 samples, 0.06%)core::slice::<impl [T]>::len (1 samples, 0.03%)memcpy (1 samples, 0.03%)tftp::instant_callback (1 samples, 0.03%)tftp::std_compat::time::Instant::from_time (1 samples, 0.03%)core::ops::function::FnOnce::call_once (1 samples, 0.03%)tftp::instant_callback::{{closure}} (1 samples, 0.03%)core::time::Duration::as_micros (1 samples, 0.03%)tftp::map::Map<K,V,_>::get_mut (1 samples, 0.03%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::as_mut_slice (1 samples, 0.03%)arrayvec::arrayvec_impl::ArrayVecImpl::as_mut_slice (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)__rust_probestack (1 samples, 0.03%)[libc.so.6] (2 samples, 0.06%)arrayvec::arrayvec::ArrayVec<T,_>::try_push (3 samples, 0.09%)arrayvec::arrayvec_impl::ArrayVecImpl::try_push (1 samples, 0.03%)arrayvec::arrayvec_impl::ArrayVecImpl::push_unchecked (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (1 samples, 0.03%)tftp::map::Map<K,V,_>::insert (8 samples, 0.23%)tftp::map::Map<K,V,_>::remove (3 samples, 0.09%)tftp::map::Map<K,V,_>::iter (2 samples, 0.06%)<&tftp::map::Map<K,V,_> as core::iter::traits::collect::IntoIterator>::into_iter (2 samples, 0.06%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (2 samples, 0.06%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (2 samples, 0.06%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (2 samples, 0.06%)core::ops::function::FnOnce::call_once (2 samples, 0.06%)tftp::instant_callback::{{closure}} (2 samples, 0.06%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (2 samples, 0.06%)clock_gettime (2 samples, 0.06%)__vdso_clock_gettime (2 samples, 0.06%)tftp::std_compat::time::Instant::elapsed (3 samples, 0.09%)core::time::Duration::from_micros (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)heapless::vec::Vec<T,_>::new (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::result::Result<T,E>::ok (27 samples, 0.77%)heapless::vec::Vec<T,_>::capacity (4 samples, 0.11%)core::mem::maybe_uninit::MaybeUninit<T>::new (30 samples, 0.85%)core::mem::manually_drop::ManuallyDrop<T>::new (5 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)core::slice::<impl [T]>::get_unchecked_mut (19 samples, 0.54%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (11 samples, 0.31%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (3 samples, 0.09%)heapless::vec::Vec<T,_>::resize (219 samples, 6.23%)heapless..heapless::vec::Vec<T,_>::push (172 samples, 4.89%)heaple..heapless::vec::Vec<T,_>::push_unchecked (144 samples, 4.10%)heap..heapless::vec::Vec<T,_>::is_full (27 samples, 0.77%)heapless::vec::Vec<T,_>::capacity (14 samples, 0.40%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (519 samples, 14.77%)<tftp::storage::FileRea..tftp::storage::FileReader<T>::read_block (222 samples, 6.32%)tftp::st..heapless::vec::Vec<T,_>::truncate (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)clap::derive::Parser::parse (1 samples, 0.03%)clap::builder::command::Command::get_matches (1 samples, 0.03%)clap::builder::command::Command::get_matches_from (1 samples, 0.03%)clap::builder::command::Command::try_get_matches_from_mut (1 samples, 0.03%)clap::builder::command::Command::_do_parse (1 samples, 0.03%)clap::parser::parser::Parser::get_matches_with (1 samples, 0.03%)clap::parser::parser::Parser::parse_subcommand (1 samples, 0.03%)clap::builder::command::Command::_build_subcommand (1 samples, 0.03%)clap::builder::command::Command::_build_self (1 samples, 0.03%)clap::builder::arg::Arg::_build (1 samples, 0.03%)read (1 samples, 0.03%)[unknown] (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.06%)[libc.so.6] (2 samples, 0.06%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.03%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.03%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (1 samples, 0.03%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (1 samples, 0.03%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.03%)core::alloc::layout::Layout::array (1 samples, 0.03%)core::alloc::layout::Layout::array::inner (1 samples, 0.03%)core::ptr::alignment::Alignment::as_usize (1 samples, 0.03%)core::result::Result<T,E>::map (1 samples, 0.03%)core::result::Result<T,E>::map_err (1 samples, 0.03%)core::ops::function::FnOnce::call_once (1 samples, 0.03%)tftp::io::from_io_err (1 samples, 0.03%)std::io::error::Error::kind (1 samples, 0.03%)std::sys::unix::decode_error_kind (1 samples, 0.03%)polling::Poller::modify (1 samples, 0.03%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (1 samples, 0.03%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.03%)alloc::vec::Vec<T,A>::extend_desugared (1 samples, 0.03%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.03%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.03%)alloc::raw_vec::finish_grow (1 samples, 0.03%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.03%)alloc::alloc::Global::alloc_impl (1 samples, 0.03%)core::ptr::non_null::NonNull<[T]>::slice_from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::sync::atomic::AtomicBool::swap (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)epoll_wait (9 samples, 0.26%)polling::Poller::wait (13 samples, 0.37%)polling::epoll::Poller::wait (11 samples, 0.31%)std::io::error::Error::last_os_error (1 samples, 0.03%)std::sys::unix::os::errno (1 samples, 0.03%)__errno_location (1 samples, 0.03%)recvfrom (1 samples, 0.03%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (20 samples, 0.57%)std::net::udp::UdpSocket::recv_from (3 samples, 0.09%)std::sys_common::net::UdpSocket::recv_from (3 samples, 0.09%)std::sys::unix::net::Socket::recv_from (3 samples, 0.09%)std::sys::unix::net::Socket::recv_from_with_flags (3 samples, 0.09%)std::sys::unix::cvt (2 samples, 0.06%)std::io::error::Error::last_os_error (2 samples, 0.06%)std::sys::unix::os::errno (2 samples, 0.06%)__errno_location (2 samples, 0.06%)heapless::vec::Vec<T,_>::truncate (1 samples, 0.03%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (2 samples, 0.06%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.03%)core::result::Result<T,E>::map (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)chacha20::xchacha::quarter_round (2 samples, 0.06%)core::num::<impl u32>::rotate_left (1 samples, 0.03%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.03%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.03%)<core::slice::iter::ChunksExactMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)chacha20::xchacha::hchacha (9 samples, 0.26%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (12 samples, 0.34%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::new (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (14 samples, 0.40%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.06%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.06%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.06%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (2 samples, 0.06%)universal_hash::UniversalHash::update (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.03%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.03%)poly1305::backend::soft::State::compute_block (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_slli_epi32 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_srli_epi32 (1 samples, 0.03%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (5 samples, 0.14%)cipher::stream::StreamCipher::try_apply_keystream (5 samples, 0.14%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (5 samples, 0.14%)cipher::stream_core::StreamCipherCore::write_keystream_block (5 samples, 0.14%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.14%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.14%)chacha20::backends::sse2::inner (5 samples, 0.14%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (5 samples, 0.14%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (5 samples, 0.14%)chacha20::backends::sse2::rounds (5 samples, 0.14%)chacha20::backends::sse2::double_quarter_round (5 samples, 0.14%)chacha20::backends::sse2::add_xor_rot (5 samples, 0.14%)core::core_arch::x86::sse2::_mm_xor_si128 (2 samples, 0.06%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (2 samples, 0.06%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (2 samples, 0.06%)<[Z] as zeroize::Zeroize>::zeroize (2 samples, 0.06%)zeroize::volatile_set (2 samples, 0.06%)core::ptr::write_volatile (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (12 samples, 0.34%)universal_hash::UniversalHash::update_padded (2 samples, 0.06%)universal_hash::UniversalHash::update (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.03%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.03%)poly1305::backend::soft::State::compute_block (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.03%)chacha20::backends::sse2::double_quarter_round (1 samples, 0.03%)chacha20::backends::sse2::add_xor_rot (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (2 samples, 0.06%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.06%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.06%)chacha20::backends::sse2::inner (2 samples, 0.06%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (2 samples, 0.06%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (2 samples, 0.06%)chacha20::backends::sse2::rounds (2 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)core::mem::replace (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (3 samples, 0.09%)cipher::stream::StreamCipher::try_apply_keystream (3 samples, 0.09%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (3 samples, 0.09%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.03%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::convert::num::ptr_try_from_impls::<impl core::convert::TryFrom<u32> for usize>::try_from (1 samples, 0.03%)cipher::stream::StreamCipherSeek::seek (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipherSeek>::try_seek (1 samples, 0.03%)<u64 as cipher::stream::SeekNum>::into_block_byte (1 samples, 0.03%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.03%)core::iter::adapters::enumerate::Enumerate<I>::new (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.09%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (35 samples, 1.00%)chacha20poly1305::cipher::Cipher<C>::new (9 samples, 0.26%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (5 samples, 0.14%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (5 samples, 0.14%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::mem::forget (1 samples, 0.03%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::recv_from (58 samples, 1.65%)tftp::encryption::Encryptor::decrypt (36 samples, 1.02%)aead::AeadInPlace::decrypt_in_place (36 samples, 1.02%)generic_array::GenericArray<T,N>::from_slice (1 samples, 0.03%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (2 samples, 0.06%)std::net::udp::UdpSocket::send_to (1 samples, 0.03%)std::sys_common::net::UdpSocket::send_to (1 samples, 0.03%)std::sys_common::net::<impl std::sys_common::IntoInner<(std::sys_common::net::SocketAddrCRepr,u32)> for &std::net::socket_addr::SocketAddr>::into_inner (1 samples, 0.03%)core::ptr::drop_in_place<core::result::Result<tftp::packet::PacketType,tftp::error::PacketError>> (2 samples, 0.06%)log::max_level (1 samples, 0.03%)core::sync::atomic::AtomicUsize::load (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.03%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::num::<impl u32>::from_le_bytes (1 samples, 0.03%)core::result::Result<T,E>::unwrap (1 samples, 0.03%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (6 samples, 0.17%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.06%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (2 samples, 0.06%)core::slice::raw::from_raw_parts (2 samples, 0.06%)core::ptr::slice_from_raw_parts (2 samples, 0.06%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (9 samples, 0.26%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (7 samples, 0.20%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.03%)core::num::<impl u32>::rotate_left (3 samples, 0.09%)chacha20::xchacha::quarter_round (27 samples, 0.77%)core::num::<impl u32>::wrapping_add (1 samples, 0.03%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.06%)core::mem::replace (2 samples, 0.06%)core::iter::traits::iterator::Iterator::zip (3 samples, 0.09%)core::slice::iter::<impl core::iter::traits::collect::IntoIterator for &[T]>::into_iter (1 samples, 0.03%)core::result::Result<T,E>::unwrap (2 samples, 0.06%)core::slice::<impl [T]>::chunks_exact (2 samples, 0.06%)core::slice::iter::ChunksExact<T>::new (1 samples, 0.03%)core::slice::<impl [T]>::split_at_unchecked (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)core::slice::<impl [T]>::copy_from_slice (2 samples, 0.06%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (4 samples, 0.11%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (4 samples, 0.11%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (8 samples, 0.23%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (7 samples, 0.20%)core::iter::traits::iterator::Iterator::fold (7 samples, 0.20%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (2 samples, 0.06%)core::ptr::read (1 samples, 0.03%)chacha20::xchacha::hchacha (69 samples, 1.96%)c..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (11 samples, 0.31%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (11 samples, 0.31%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.09%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.09%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::iter_position (2 samples, 0.06%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (82 samples, 2.33%)<..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (6 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (6 samples, 0.17%)generic_array::ArrayBuilder<T,N>::new (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (6 samples, 0.17%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (5 samples, 0.14%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (4 samples, 0.11%)core::iter::traits::iterator::Iterator::for_each (10 samples, 0.28%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (10 samples, 0.28%)core::iter::traits::iterator::Iterator::fold (10 samples, 0.28%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (94 samples, 2.68%)<c..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (11 samples, 0.31%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (11 samples, 0.31%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::slice::<impl [T]>::copy_from_slice (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.09%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (8 samples, 0.23%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (8 samples, 0.23%)poly1305::backend::soft::State::finalize_mut (8 samples, 0.23%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.11%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.11%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::result::Result<T,E>::map_err (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.09%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (6 samples, 0.17%)universal_hash::UniversalHash::update (2 samples, 0.06%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (2 samples, 0.06%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (2 samples, 0.06%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (2 samples, 0.06%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.03%)poly1305::backend::soft::State::compute_block (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (63 samples, 1.79%)c..core::core_arch::x86::m128iExt::as_i32x4 (12 samples, 0.34%)core::core_arch::x86::sse2::_mm_slli_epi32 (38 samples, 1.08%)core::core_arch::x86::m128iExt::as_i32x4 (7 samples, 0.20%)core::core_arch::x86::sse2::_mm_srli_epi32 (8 samples, 0.23%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.06%)chacha20::backends::sse2::add_xor_rot (266 samples, 7.57%)chacha20::..core::core_arch::x86::sse2::_mm_xor_si128 (31 samples, 0.88%)chacha20::backends::sse2::cols_to_rows (15 samples, 0.43%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (11 samples, 0.31%)core::core_arch::x86::m128iExt::as_i32x4 (3 samples, 0.09%)chacha20::backends::sse2::double_quarter_round (301 samples, 8.57%)chacha20::ba..chacha20::backends::sse2::rows_to_cols (15 samples, 0.43%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (12 samples, 0.34%)core::core_arch::x86::m128iExt::as_i32x4 (5 samples, 0.14%)core::core_arch::x86::sse2::_mm_add_epi32 (4 samples, 0.11%)<usize as core::iter::range::Step>::forward_unchecked (4 samples, 0.11%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.06%)core::ptr::read (6 samples, 0.17%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)chacha20::backends::sse2::rounds (337 samples, 9.59%)chacha20::back..core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (27 samples, 0.77%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (26 samples, 0.74%)core::mem::replace (10 samples, 0.28%)core::ptr::write (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_storeu_si128 (1 samples, 0.03%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.06%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (351 samples, 9.99%)<chacha20::bac..core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (7 samples, 0.20%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (7 samples, 0.20%)core::mem::replace (4 samples, 0.11%)core::ptr::read (1 samples, 0.03%)<inout::inout_buf::InOutBufIter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.03%)core::ptr::write (13 samples, 0.37%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (118 samples, 3.36%)<co..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (72 samples, 2.05%)c..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (48 samples, 1.37%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (6 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::is_null (19 samples, 0.54%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (7 samples, 0.20%)core::ptr::mut_ptr::<impl *mut T>::addr (4 samples, 0.11%)core::ptr::mut_ptr::<impl *mut T>::add (12 samples, 0.34%)core::ptr::mut_ptr::<impl *mut T>::offset (12 samples, 0.34%)core::ptr::non_null::NonNull<T>::as_ptr (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each (244 samples, 6.94%)core::ite..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (243 samples, 6.92%)<core::it..core::iter::traits::iterator::Iterator::fold (242 samples, 6.89%)core::ite..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (79 samples, 2.25%)<..core::slice::iter::IterMut<T>::post_inc_start (43 samples, 1.22%)core::ptr::non_null::NonNull<T>::new_unchecked (3 samples, 0.09%)[libc.so.6] (2 samples, 0.06%)core::ptr::read (3 samples, 0.09%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.09%)memcpy (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (4 samples, 0.11%)memcpy (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (256 samples, 7.29%)generic_ar..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (256 samples, 7.29%)<generic_a..generic_array::ArrayBuilder<T,N>::iter_position (4 samples, 0.11%)core::slice::<impl [T]>::iter_mut (2 samples, 0.06%)core::slice::iter::IterMut<T>::new (2 samples, 0.06%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (47 samples, 1.34%)core::slice::raw::from_raw_parts (34 samples, 0.97%)core::ptr::slice_from_raw_parts (26 samples, 0.74%)core::ptr::metadata::from_raw_parts (22 samples, 0.63%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (19 samples, 0.54%)core::slice::raw::from_raw_parts_mut (15 samples, 0.43%)core::ptr::slice_from_raw_parts_mut (13 samples, 0.37%)core::ptr::metadata::from_raw_parts_mut (9 samples, 0.26%)<usize as core::iter::range::Step>::forward_unchecked (17 samples, 0.48%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (9 samples, 0.26%)core::ptr::read (24 samples, 0.68%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (4 samples, 0.11%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (4 samples, 0.11%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (90 samples, 2.56%)co..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (86 samples, 2.45%)<c..core::mem::replace (32 samples, 0.91%)core::ptr::write (3 samples, 0.09%)[libc.so.6] (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (2 samples, 0.06%)memcpy (2 samples, 0.06%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (5 samples, 0.14%)memcpy (1 samples, 0.03%)core::ptr::read (7 samples, 0.20%)memcpy (1 samples, 0.03%)core::ptr::write (13 samples, 0.37%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (86 samples, 2.45%)<c..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (58 samples, 1.65%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (39 samples, 1.11%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (7 samples, 0.20%)<u8 as core::default::Default>::default (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null (16 samples, 0.46%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (5 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::addr (4 samples, 0.11%)core::ptr::mut_ptr::<impl *mut T>::add (9 samples, 0.26%)core::ptr::mut_ptr::<impl *mut T>::offset (7 samples, 0.20%)core::ptr::non_null::NonNull<T>::as_ptr (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each (220 samples, 6.26%)core::it..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (219 samples, 6.23%)<core::i..core::iter::traits::iterator::Iterator::fold (219 samples, 6.23%)core::it..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (71 samples, 2.02%)<..core::slice::iter::IterMut<T>::post_inc_start (38 samples, 1.08%)core::ptr::non_null::NonNull<T>::new_unchecked (5 samples, 0.14%)core::mem::forget (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)memcpy (1 samples, 0.03%)core::ptr::read (2 samples, 0.06%)memcpy (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (4 samples, 0.11%)memcpy (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::iter_position (2 samples, 0.06%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (1,125 samples, 32.01%)cipher::stream_core::StreamCipherCore::apply_keystre..<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,125 samples, 32.01%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream..<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,125 samples, 32.01%)<chacha20::ChaChaCore<R> as cipher::stream_core::Str..chacha20::backends::sse2::inner (1,125 samples, 32.01%)chacha20::backends::sse2::inner<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (1,124 samples, 31.99%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::..inout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (513 samples, 14.60%)inout::inout::InOut<ge..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (230 samples, 6.55%)generic_a..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (230 samples, 6.55%)<generic_..generic_array::ArrayBuilder<T,N>::new (2 samples, 0.06%)core::core_arch::x86::sse2::_mm_add_epi32 (4 samples, 0.11%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.06%)core::core_arch::x86::sse2::_mm_slli_epi32 (3 samples, 0.09%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)chacha20::backends::sse2::add_xor_rot (18 samples, 0.51%)core::core_arch::x86::sse2::_mm_xor_si128 (2 samples, 0.06%)chacha20::backends::sse2::double_quarter_round (20 samples, 0.57%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (23 samples, 0.65%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (23 samples, 0.65%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (23 samples, 0.65%)chacha20::backends::sse2::inner (23 samples, 0.65%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (22 samples, 0.63%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (22 samples, 0.63%)chacha20::backends::sse2::rounds (21 samples, 0.60%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (1,157 samples, 32.93%)cipher::stream::StreamCipher::apply_keystreamcipher::stream::StreamCipher::try_apply_keystream (1,157 samples, 32.93%)cipher::stream::StreamCipher::try_apply_keystream<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1,157 samples, 32.93%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> a..inout::inout_buf::InOutBuf<u8>::xor_in2out (8 samples, 0.23%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.11%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.11%)core::mem::replace (2 samples, 0.06%)core::ptr::read (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.11%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.11%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (11 samples, 0.31%)<[Z] as zeroize::Zeroize>::zeroize (10 samples, 0.28%)zeroize::volatile_set (8 samples, 0.23%)core::ptr::write_volatile (2 samples, 0.06%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (15 samples, 0.43%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (4 samples, 0.11%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (4 samples, 0.11%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (3 samples, 0.09%)<[Z: N] as zeroize::Zeroize>::zeroize (3 samples, 0.09%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (3 samples, 0.09%)<&mut I as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)core::slice::<impl [T]>::len (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (5 samples, 0.14%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (3 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (9 samples, 0.26%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (8 samples, 0.23%)core::iter::traits::iterator::Iterator::fold (8 samples, 0.23%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (10 samples, 0.28%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (10 samples, 0.28%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (15 samples, 0.43%)<T as core::convert::TryInto<U>>::try_into (73 samples, 2.08%)<..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (65 samples, 1.85%)c..core::result::Result<T,E>::map (36 samples, 1.02%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (7 samples, 0.20%)core::ptr::const_ptr::<impl *const T>::cast (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (8 samples, 0.23%)core::slice::raw::from_raw_parts (7 samples, 0.20%)core::ptr::slice_from_raw_parts (2 samples, 0.06%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)core::convert::num::<impl core::convert::From<u32> for u64>::from (7 samples, 0.20%)core::num::<impl u32>::from_le_bytes (23 samples, 0.65%)core::num::<impl u32>::from_ne_bytes (11 samples, 0.31%)core::result::Result<T,E>::unwrap (32 samples, 0.91%)core::ptr::const_ptr::<impl *const T>::add (5 samples, 0.14%)core::ptr::const_ptr::<impl *const T>::offset (3 samples, 0.09%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (1,466 samples, 41.72%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detacheduniversal_hash::UniversalHash::update_padded (278 samples, 7.91%)universal_h..universal_hash::UniversalHash::update (267 samples, 7.60%)universal_..<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (267 samples, 7.60%)<poly1305:..<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (267 samples, 7.60%)<poly1305:..<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (266 samples, 7.57%)<universal..<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (259 samples, 7.37%)<poly1305:..poly1305::backend::soft::State::compute_block (259 samples, 7.37%)poly1305::..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (39 samples, 1.11%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (36 samples, 1.02%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (31 samples, 0.88%)core::ptr::slice_from_raw_parts (7 samples, 0.20%)core::ptr::metadata::from_raw_parts (5 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<[Z] as zeroize::Zeroize>::zeroize (3 samples, 0.09%)zeroize::volatile_set (3 samples, 0.09%)core::ptr::write_volatile (2 samples, 0.06%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)poly1305::backend::autodetect::avx2_cpuid::init_get (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.03%)core::result::Result<T,E>::map (1 samples, 0.03%)<poly1305::backend::soft::State as core::default::Default>::default (3 samples, 0.09%)core::array::<impl core::default::Default for [T: _]>::default (3 samples, 0.09%)<u32 as core::default::Default>::default (1 samples, 0.03%)core::num::<impl u32>::from_le_bytes (1 samples, 0.03%)core::num::<impl u32>::from_ne_bytes (1 samples, 0.03%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (9 samples, 0.26%)poly1305::backend::autodetect::State::new (8 samples, 0.23%)poly1305::backend::soft::State::new (6 samples, 0.17%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (2 samples, 0.06%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.06%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2 samples, 0.06%)chacha20::backends::sse2::inner (2 samples, 0.06%)core::core_arch::x86::sse2::_mm_add_epi32 (2 samples, 0.06%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_slli_epi32 (1 samples, 0.03%)chacha20::backends::sse2::add_xor_rot (14 samples, 0.40%)core::core_arch::x86::sse2::_mm_xor_si128 (4 samples, 0.11%)chacha20::backends::sse2::double_quarter_round (16 samples, 0.46%)chacha20::backends::sse2::cols_to_rows (2 samples, 0.06%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (2 samples, 0.06%)<usize as core::iter::range::Step>::forward_unchecked (2 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.03%)chacha20::backends::sse2::rounds (21 samples, 0.60%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.14%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.11%)core::mem::replace (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (23 samples, 0.65%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (23 samples, 0.65%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (23 samples, 0.65%)chacha20::backends::sse2::inner (23 samples, 0.65%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (23 samples, 0.65%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (23 samples, 0.65%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (3 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.06%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (35 samples, 1.00%)cipher::stream::StreamCipher::try_apply_keystream (35 samples, 1.00%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (34 samples, 0.97%)inout::inout_buf::InOutBuf<u8>::xor_in2out (9 samples, 0.26%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.03%)core::ptr::const_ptr::<impl *const T>::offset (1 samples, 0.03%)cipher::stream::StreamCipherSeek::seek (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipherSeek>::try_seek (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (4 samples, 0.11%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (8 samples, 0.23%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (8 samples, 0.23%)core::iter::traits::iterator::Iterator::fold (8 samples, 0.23%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)core::slice::iter::IterMut<T>::post_inc_start (2 samples, 0.06%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (1,617 samples, 46.02%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_pl..chacha20poly1305::cipher::Cipher<C>::new (57 samples, 1.62%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (9 samples, 0.26%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (9 samples, 0.26%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)core::result::Result<T,E>::map_err (1 samples, 0.03%)tftp::encryption::Encryptor::encrypt (1,623 samples, 46.19%)tftp::encryption::Encryptor::encryptaead::AeadInPlace::encrypt_in_place (1,623 samples, 46.19%)aead::AeadInPlace::encrypt_in_place<heapless::vec::Vec<u8,_> as aead::Buffer>::extend_from_slice (5 samples, 0.14%)heapless::vec::Vec<T,_>::extend_from_slice (4 samples, 0.11%)heapless::vec::Vec<T,_>::push_unchecked (3 samples, 0.09%)tftp::packet::PacketType::from_repr (2 samples, 0.06%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_to (1,632 samples, 46.44%)<tftp::socket::EncryptionBoundSocket<S> as tftp::socket::Socket>::send_totftp::packet::PacketType::from_bytes (4 samples, 0.11%)tftp::packet::try_from (2 samples, 0.06%)core::num::<impl u16>::from_be_bytes (1 samples, 0.03%)core::option::Option<T>::map (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::pop_at (1 samples, 0.03%)<arrayvec::arrayvec::Drain<T,_> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::option::Option<T>::map (1 samples, 0.03%)<arrayvec::arrayvec::Drain<T,_> as core::iter::traits::iterator::Iterator>::next::{{closure}} (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::free_block (3 samples, 0.09%)tftp::map::Map<K,V,_>::remove (2 samples, 0.06%)core::option::Option<T>::and_then (2 samples, 0.06%)tftp::map::Map<K,V,_>::remove::{{closure}} (2 samples, 0.06%)core::option::Option<T>::map (1 samples, 0.03%)tftp::map::Map<K,V,_>::remove::{{closure}}::{{closure}} (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (4 samples, 0.11%)core::cmp::PartialEq::ne (1 samples, 0.03%)tftp::flow_control::RateControl::start_rtt (1 samples, 0.03%)tftp::instant_callback (1 samples, 0.03%)tftp::std_compat::time::Instant::from_time (1 samples, 0.03%)core::ops::function::FnOnce::call_once (1 samples, 0.03%)tftp::instant_callback::{{closure}} (1 samples, 0.03%)core::time::Duration::as_micros (1 samples, 0.03%)tftp::packet::PacketType::from_bytes (1 samples, 0.03%)tftp::packet::PacketType::from_repr (1 samples, 0.03%)core::ops::function::FnOnce::call_once (4 samples, 0.11%)tftp::instant_callback::{{closure}} (4 samples, 0.11%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (3 samples, 0.09%)clock_gettime (3 samples, 0.09%)__vdso_clock_gettime (3 samples, 0.09%)[[vdso]] (1 samples, 0.03%)all (3,514 samples, 100%)tftp (3,514 samples, 100.00%)tftp[unknown] (3,508 samples, 99.83%)[unknown]tftp::client::client::send_file (1,709 samples, 48.63%)tftp::client::client::send_filetftp::std_compat::time::Instant::elapsed (5 samples, 0.14%)core::time::Duration::from_micros (1 samples, 0.03%)core::time::Duration::new (1 samples, 0.03%)core::num::<impl u64>::checked_add (1 samples, 0.03%) \ No newline at end of file diff --git a/info/send_flamegraph_no_encryption_alloc.svg b/info/send_flamegraph_no_encryption_alloc.svg new file mode 100644 index 0000000..24cea91 --- /dev/null +++ b/info/send_flamegraph_no_encryption_alloc.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [ld-linux-x86-64.so.2] (1 samples, 0.14%)[ld-linux-x86-64.so.2] (1 samples, 0.14%)[ld-linux-x86-64.so.2] (1 samples, 0.14%)[ld-linux-x86-64.so.2] (6 samples, 0.85%)[unknown] (1 samples, 0.14%)[unknown] (1 samples, 0.14%)<tftp::cli::ClientCliConfig as clap::derive::Args>::augment_args (1 samples, 0.14%)clap::builder::arg::Arg::required (1 samples, 0.14%)[libc.so.6] (1 samples, 0.14%)core::const_closure::ConstFnMutClosure<&mut CapturedData,Function>::new (1 samples, 0.14%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.28%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.14%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (1 samples, 0.14%)core::ops::function::Fn::call (1 samples, 0.14%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.57%)core::ptr::drop_in_place<core::array::iter::IntoIter<u8,2_usize>> (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.14%)core::array::iter::IntoIter<T,_>::as_mut_slice (1 samples, 0.14%)core::slice::<impl [T]>::get_unchecked_mut (1 samples, 0.14%)core::ptr::const_ptr::<impl *const T>::is_null (4 samples, 0.57%)core::ptr::mut_ptr::<impl *mut T>::is_null (5 samples, 0.71%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (4 samples, 0.57%)core::ptr::mut_ptr::<impl *mut T>::addr (4 samples, 0.57%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::add (18 samples, 2.56%)co..core::ptr::mut_ptr::<impl *mut T>::offset (18 samples, 2.56%)co..<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (77 samples, 10.95%)<core::slice::it..core::slice::iter::Iter<T>::post_inc_start (47 samples, 6.69%)core::sli..core::ptr::non_null::NonNull<T>::new_unchecked (6 samples, 0.85%)alloc::vec::set_len_on_drop::SetLenOnDrop::current_len (5 samples, 0.71%)core::ptr::mut_ptr::<impl *mut T>::add (11 samples, 1.56%)core::ptr::mut_ptr::<impl *mut T>::offset (11 samples, 1.56%)core::iter::adapters::copied::copy_fold::{{closure}} (88 samples, 12.52%)core::iter::adapter..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (64 samples, 9.10%)core::iter::t..alloc::vec::Vec<T,A>::extend_trusted::{{closure}} (44 samples, 6.26%)alloc::v..core::ptr::write (18 samples, 2.56%)co..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (222 samples, 31.58%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::S..alloc::vec::Vec<T,A>::extend_trusted (221 samples, 31.44%)alloc::vec::Vec<T,A>::extend_trustedcore::iter::traits::iterator::Iterator::for_each (221 samples, 31.44%)core::iter::traits::iterator::Iterator::for_each<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (221 samples, 31.44%)<core::iter::adapters::chain::Chain<A,B> as core::i..<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::fold (217 samples, 30.87%)<core::iter::adapters::copied::Copied<I> as core::..core::iter::traits::iterator::Iterator::fold (217 samples, 30.87%)core::iter::traits::iterator::Iterator::foldcore::ptr::drop_in_place<core::iter::adapters::copied::copy_fold<u8,(),core::iter::traits::iterator::Iterator::for_each::call<u8,alloc::vec::Vec<u8>::extend_trusted<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>>>::{{closure}}>::{{closure}}>::{{closure}}> (3 samples, 0.43%)core::ptr::drop_in_place<core::iter::traits::iterator::Iterator::for_each::call<u8,alloc::vec::Vec<u8>::extend_trusted<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>>>::{{closure}}>::{{closure}}> (2 samples, 0.28%)core::ptr::drop_in_place<alloc::vec::Vec<u8>::extend_trusted<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>>>::{{closure}}> (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::iter::traits::exact_size::ExactSizeIterator>::len (1 samples, 0.14%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.28%)<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.14%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.14%)__rdl_alloc (1 samples, 0.14%)alloc::alloc::alloc (2 samples, 0.28%)malloc (1 samples, 0.14%)[libc.so.6] (1 samples, 0.14%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (230 samples, 32.72%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nes..alloc::vec::Vec<T>::with_capacity (5 samples, 0.71%)alloc::vec::Vec<T,A>::with_capacity_in (5 samples, 0.71%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (5 samples, 0.71%)alloc::raw_vec::RawVec<T,A>::allocate_in (5 samples, 0.71%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (5 samples, 0.71%)alloc::alloc::Global::alloc_impl (4 samples, 0.57%)core::ptr::non_null::NonNull<[T]>::slice_from_raw_parts (2 samples, 0.28%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (231 samples, 32.86%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::Sp..[libc.so.6] (1 samples, 0.14%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (232 samples, 33.00%)<tftp::packet::DataPacket as tftp::packet::ByteConver..core::iter::traits::iterator::Iterator::collect (232 samples, 33.00%)core::iter::traits::iterator::Iterator::collect<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (232 samples, 33.00%)<alloc::vec::Vec<T> as core::iter::traits::collect::F..[libc.so.6] (1 samples, 0.14%)core::array::iter::<impl core::iter::traits::collect::IntoIterator for [T: N]>::into_iter (1 samples, 0.14%)core::iter::traits::iterator::Iterator::chain (1 samples, 0.14%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.14%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.14%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.28%)core::iter::traits::iterator::Iterator::try_fold (2 samples, 0.28%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (1 samples, 0.14%)core::ops::function::Fn::call (1 samples, 0.14%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.57%)core::ptr::drop_in_place<core::array::iter::IntoIter<u8,2_usize>> (1 samples, 0.14%)<core::array::iter::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.14%)core::array::iter::IntoIter<T,_>::as_mut_slice (1 samples, 0.14%)core::slice::<impl [T]>::get_unchecked_mut (1 samples, 0.14%)<core::ops::index_range::IndexRange as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.14%)core::ptr::const_ptr::<impl *const T>::add (3 samples, 0.43%)core::ptr::const_ptr::<impl *const T>::offset (3 samples, 0.43%)<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::next (49 samples, 6.97%)<alloc::v..core::ptr::read (10 samples, 1.42%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (4 samples, 0.57%)alloc::vec::set_len_on_drop::SetLenOnDrop::current_len (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::add (12 samples, 1.71%)core::ptr::mut_ptr::<impl *mut T>::offset (12 samples, 1.71%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (56 samples, 7.97%)core::iter:..alloc::vec::Vec<T,A>::extend_trusted::{{closure}} (41 samples, 5.83%)alloc::..core::ptr::write (11 samples, 1.56%)<T as core::convert::Into<U>>::into (1 samples, 0.14%)<core::ptr::non_null::NonNull<T> as core::convert::From<core::ptr::unique::Unique<T>>>::from (1 samples, 0.14%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (172 samples, 24.47%)<alloc::vec::Vec<T,A> as alloc::vec::sp..alloc::vec::Vec<T,A>::extend_trusted (172 samples, 24.47%)alloc::vec::Vec<T,A>::extend_trustedcore::iter::traits::iterator::Iterator::for_each (171 samples, 24.32%)core::iter::traits::iterator::Iterator:..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (171 samples, 24.32%)<core::iter::adapters::chain::Chain<A,B..core::iter::traits::iterator::Iterator::fold (167 samples, 23.76%)core::iter::traits::iterator::Iterator..core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u8>> (3 samples, 0.43%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (3 samples, 0.43%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u8,alloc::alloc::Global>> (3 samples, 0.43%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (3 samples, 0.43%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (2 samples, 0.28%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.28%)alloc::raw_vec::RawVec<T,A>::current_memory (2 samples, 0.28%)core::alloc::layout::Layout::array (1 samples, 0.14%)core::alloc::layout::Layout::array::inner (1 samples, 0.14%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (174 samples, 24.75%)<alloc::vec::Vec<T> as core::iter::trai..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (174 samples, 24.75%)<alloc::vec::Vec<T> as alloc::vec::spec..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (174 samples, 24.75%)<alloc::vec::Vec<T> as alloc::vec::spec..alloc::vec::Vec<T>::with_capacity (2 samples, 0.28%)alloc::vec::Vec<T,A>::with_capacity_in (2 samples, 0.28%)alloc::raw_vec::RawVec<T,A>::with_capacity_in (2 samples, 0.28%)alloc::raw_vec::RawVec<T,A>::allocate_in (2 samples, 0.28%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (2 samples, 0.28%)alloc::alloc::Global::alloc_impl (2 samples, 0.28%)alloc::alloc::alloc (2 samples, 0.28%)malloc (2 samples, 0.28%)[libc.so.6] (2 samples, 0.28%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (409 samples, 58.18%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytescore::iter::traits::iterator::Iterator::collect (175 samples, 24.89%)core::iter::traits::iterator::Iterator::..memcpy (1 samples, 0.14%)core::result::Result<T,E>::map (1 samples, 0.14%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.28%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (2 samples, 0.28%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (2 samples, 0.28%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.14%)core::result::Result<T,E>::map_err (5 samples, 0.71%)core::ops::function::FnOnce::call_once (5 samples, 0.71%)tftp::io::from_io_err (5 samples, 0.71%)std::io::error::Error::kind (3 samples, 0.43%)std::io::error::repr_bitpacked::Repr::data (3 samples, 0.43%)std::io::error::repr_bitpacked::decode_repr (3 samples, 0.43%)epoll_wait (17 samples, 2.42%)ep..<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (27 samples, 3.84%)<tft..polling::Poller::wait (21 samples, 2.99%)pol..polling::epoll::Poller::wait (21 samples, 2.99%)pol..polling::epoll::Poller::modify (1 samples, 0.14%)polling::epoll::Poller::ctl (1 samples, 0.14%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (1 samples, 0.14%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (3 samples, 0.43%)std::net::udp::UdpSocket::send_to (2 samples, 0.28%)<tftp::std_compat::io::ErrorKind as core::cmp::PartialEq>::eq (1 samples, 0.14%)alloc::collections::btree::node::Handle<Node,Type>::idx (1 samples, 0.14%)alloc::collections::btree::map::entry::OccupiedEntry<K,V,A>::remove_entry (4 samples, 0.57%)alloc::collections::btree::map::entry::OccupiedEntry<K,V,A>::remove_kv (4 samples, 0.57%)alloc::collections::btree::remove::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking (4 samples, 0.57%)alloc::collections::btree::remove::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv (4 samples, 0.57%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::LeafOrInternal>::choose_parent_kv (2 samples, 0.28%)alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>::ascend (2 samples, 0.28%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove_entry (6 samples, 0.85%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (2 samples, 0.28%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (2 samples, 0.28%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (2 samples, 0.28%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut,K,V,Type>::keys (1 samples, 0.14%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.14%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.14%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.14%)core::ptr::slice_from_raw_parts (1 samples, 0.14%)core::ptr::metadata::from_raw_parts (1 samples, 0.14%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove::{{closure}} (1 samples, 0.14%)[libc.so.6] (1 samples, 0.14%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (9 samples, 1.28%)core::option::Option<T>::map (3 samples, 0.43%)memcpy (2 samples, 0.28%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::RangeInclusive<A>>::next (1 samples, 0.14%)<core::ops::range::RangeInclusive<T> as core::iter::range::RangeInclusiveIteratorImpl>::spec_next (1 samples, 0.14%)core::ops::range::RangeInclusive<Idx>::is_empty (1 samples, 0.14%)core::cmp::impls::<impl core::cmp::PartialOrd for u64>::le (1 samples, 0.14%)__rdl_dealloc (1 samples, 0.14%)std::sys::unix::alloc::<impl core::alloc::global::GlobalAlloc for std::alloc::System>::dealloc (1 samples, 0.14%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::free_block (12 samples, 1.71%)core::option::Option<T>::map (2 samples, 0.28%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::free_block::{{closure}} (2 samples, 0.28%)core::ptr::drop_in_place<tftp::storage::TimedBlock> (2 samples, 0.28%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (2 samples, 0.28%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (2 samples, 0.28%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.28%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (2 samples, 0.28%)alloc::alloc::dealloc (2 samples, 0.28%)cfree (1 samples, 0.14%)[libc.so.6] (1 samples, 0.14%)[libc.so.6] (1 samples, 0.14%)<alloc::vec::Vec<T,A> as core::clone::Clone>::clone (1 samples, 0.14%)alloc::vec::Vec<T,A>::allocator (1 samples, 0.14%)alloc::raw_vec::RawVec<T,A>::allocator (1 samples, 0.14%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,Type>::force (1 samples, 0.14%)alloc::collections::btree::map::BTreeMap<K,V,A>::get_mut (3 samples, 0.43%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (3 samples, 0.43%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (2 samples, 0.28%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (2 samples, 0.28%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.28%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.28%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.14%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.14%)alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>::reborrow (1 samples, 0.14%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (3 samples, 0.43%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (3 samples, 0.43%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (3 samples, 0.43%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.14%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.14%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.14%)alloc::collections::btree::map::BTreeMap<K,V,A>::entry (5 samples, 0.71%)memcpy (1 samples, 0.14%)core::mem::maybe_uninit::MaybeUninit<T>::write (1 samples, 0.14%)memcpy (1 samples, 0.14%)alloc::collections::btree::map::BTreeMap<K,V,A>::insert (11 samples, 1.56%)alloc::collections::btree::map::entry::VacantEntry<K,V,A>::insert (6 samples, 0.85%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::insert_recursing (4 samples, 0.57%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::insert (4 samples, 0.57%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::insert_fit (4 samples, 0.57%)alloc::collections::btree::node::slice_insert (3 samples, 0.43%)core::slice::<impl [T]>::len (1 samples, 0.14%)core::ptr::metadata::metadata (1 samples, 0.14%)core::ptr::drop_in_place<core::option::Option<tftp::storage::TimedBlock>> (1 samples, 0.14%)tftp::instant_callback (1 samples, 0.14%)tftp::std_compat::time::Instant::elapsed (1 samples, 0.14%)core::ops::function::FnOnce::call_once (1 samples, 0.14%)tftp::instant_callback::{{closure}} (1 samples, 0.14%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.14%)std::sys::unix::cvt (1 samples, 0.14%)<i32 as std::sys::unix::IsMinusOne>::is_minus_one (1 samples, 0.14%)<alloc::vec::ExtendElement<T> as alloc::vec::ExtendWith<T>>::next (5 samples, 0.71%)core::clone::impls::<impl core::clone::Clone for u8>::clone (1 samples, 0.14%)alloc::alloc::alloc (2 samples, 0.28%)malloc (2 samples, 0.28%)[libc.so.6] (1 samples, 0.14%)core::option::Option<T>::ok_or (1 samples, 0.14%)alloc::raw_vec::finish_grow (6 samples, 0.85%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (4 samples, 0.57%)alloc::alloc::Global::alloc_impl (4 samples, 0.57%)core::ptr::non_null::NonNull<[T]>::slice_from_raw_parts (1 samples, 0.14%)alloc::vec::Vec<T,A>::reserve (7 samples, 1.00%)alloc::raw_vec::RawVec<T,A>::reserve (7 samples, 1.00%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (7 samples, 1.00%)alloc::raw_vec::RawVec<T,A>::grow_amortized (7 samples, 1.00%)core::cmp::max (1 samples, 0.14%)core::cmp::Ord::max (1 samples, 0.14%)core::cmp::max_by (1 samples, 0.14%)alloc::vec::set_len_on_drop::SetLenOnDrop::increment_len (3 samples, 0.43%)<usize as core::iter::range::Step>::forward_unchecked (13 samples, 1.85%)<..core::num::<impl usize>::unchecked_add (1 samples, 0.14%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (7 samples, 1.00%)core::ptr::read (33 samples, 4.69%)core:..core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.43%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (3 samples, 0.43%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (108 samples, 15.36%)core::iter::range::<impl..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (100 samples, 14.22%)<core::ops::range::Ran..core::mem::replace (57 samples, 8.11%)core::mem::..core::ptr::write (3 samples, 0.43%)core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.43%)core::ptr::mut_ptr::<impl *mut T>::offset (3 samples, 0.43%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (202 samples, 28.73%)<tftp::storage::FileReader<T> as tftp::storage..tftp::storage::FileReader<T>::read_block (181 samples, 25.75%)tftp::storage::FileReader<T>::read_blockalloc::vec::Vec<T,A>::resize (180 samples, 25.60%)alloc::vec::Vec<T,A>::resizealloc::vec::Vec<T,A>::extend_with (180 samples, 25.60%)alloc::vec::Vec<T,A>::extend_withcore::ptr::write (19 samples, 2.70%)co..<alloc::vec::ExtendElement<T> as alloc::vec::ExtendWith<T>>::next (1 samples, 0.14%)<usize as core::iter::range::Step>::forward_unchecked (3 samples, 0.43%)core::num::<impl usize>::unchecked_add (1 samples, 0.14%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.14%)core::ptr::read (5 samples, 0.71%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (14 samples, 1.99%)c..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (14 samples, 1.99%)<..core::mem::replace (8 samples, 1.14%)core::ptr::write (1 samples, 0.14%)alloc::vec::Vec<T,A>::resize (28 samples, 3.98%)allo..alloc::vec::Vec<T,A>::extend_with (28 samples, 3.98%)allo..core::ptr::write (8 samples, 1.14%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.14%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::cast (1 samples, 0.14%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (3 samples, 0.43%)alloc::alloc::dealloc (3 samples, 0.43%)cfree (3 samples, 0.43%)[libc.so.6] (1 samples, 0.14%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (5 samples, 0.71%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (4 samples, 0.57%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (4 samples, 0.57%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.14%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.14%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.14%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.14%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (1 samples, 0.14%)alloc::alloc::dealloc (1 samples, 0.14%)core::ptr::drop_in_place<tftp::storage::Block> (4 samples, 0.57%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (3 samples, 0.43%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (2 samples, 0.28%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.28%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.14%)core::alloc::layout::Layout::array (1 samples, 0.14%)core::alloc::layout::Layout::array::inner (1 samples, 0.14%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.14%)clock_gettime (1 samples, 0.14%)__vdso_clock_gettime (1 samples, 0.14%)core::ops::function::FnOnce::call_once (2 samples, 0.28%)tftp::instant_callback::{{closure}} (2 samples, 0.28%)std::time::SystemTime::duration_since (1 samples, 0.14%)std::sys::unix::time::SystemTime::sub_time (1 samples, 0.14%)std::sys::unix::time::Timespec::sub_timespec (1 samples, 0.14%)all (703 samples, 100%)tftp (703 samples, 100.00%)tftp_start (696 samples, 99.00%)_start__libc_start_main (696 samples, 99.00%)__libc_start_main[libc.so.6] (696 samples, 99.00%)[libc.so.6]main (696 samples, 99.00%)mainstd::rt::lang_start (696 samples, 99.00%)std::rt::lang_startstd::rt::lang_start_internal (696 samples, 99.00%)std::rt::lang_start_internalstd::panic::catch_unwind (696 samples, 99.00%)std::panic::catch_unwindstd::panicking::try (696 samples, 99.00%)std::panicking::trystd::panicking::try::do_call (696 samples, 99.00%)std::panicking::try::do_callstd::rt::lang_start_internal::{{closure}} (696 samples, 99.00%)std::rt::lang_start_internal::{{closure}}std::panic::catch_unwind (696 samples, 99.00%)std::panic::catch_unwindstd::panicking::try (696 samples, 99.00%)std::panicking::trystd::panicking::try::do_call (696 samples, 99.00%)std::panicking::try::do_callcore::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (696 samples, 99.00%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_oncestd::rt::lang_start::{{closure}} (696 samples, 99.00%)std::rt::lang_start::{{closure}}std::sys_common::backtrace::__rust_begin_short_backtrace (696 samples, 99.00%)std::sys_common::backtrace::__rust_begin_short_backtracecore::ops::function::FnOnce::call_once (696 samples, 99.00%)core::ops::function::FnOnce::call_oncetftp::main (696 samples, 99.00%)tftp::maintftp::start_send (696 samples, 99.00%)tftp::start_sendtftp::client::client::send_file (696 samples, 99.00%)tftp::client::client::send_filetftp::std_compat::time::Instant::elapsed (3 samples, 0.43%)core::time::Duration::from_micros (1 samples, 0.14%)core::time::Duration::new (1 samples, 0.14%) \ No newline at end of file diff --git a/info/send_flamegraph_no_encryption_stack.svg b/info/send_flamegraph_no_encryption_stack.svg new file mode 100644 index 0000000..81c0bd4 --- /dev/null +++ b/info/send_flamegraph_no_encryption_stack.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [ld-linux-x86-64.so.2] (1 samples, 0.06%)[ld-linux-x86-64.so.2] (1 samples, 0.06%)[ld-linux-x86-64.so.2] (1 samples, 0.06%)[ld-linux-x86-64.so.2] (6 samples, 0.36%)[unknown] (1 samples, 0.06%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (2 samples, 0.12%)core::ops::function::FnOnce::call_once (1 samples, 0.06%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.06%)core::option::Option<T>::map (1 samples, 0.06%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next::{{closure}} (1 samples, 0.06%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.06%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.06%)core::option::Option<T>::as_mut (2 samples, 0.12%)core::iter::adapters::chain::and_then_or_clear (16 samples, 0.95%)core::option::Option<T>::is_none (1 samples, 0.06%)core::ptr::const_ptr::<impl *const T>::is_null (25 samples, 1.48%)core::ptr::const_ptr::<impl *const T>::is_null::runtime_impl (8 samples, 0.47%)core::ptr::const_ptr::<impl *const T>::addr (6 samples, 0.36%)core::ptr::mut_ptr::<impl *mut T>::is_null (12 samples, 0.71%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (7 samples, 0.41%)core::ptr::mut_ptr::<impl *mut T>::addr (6 samples, 0.36%)core::ptr::mut_ptr::<impl *mut T>::add (5 samples, 0.30%)core::ptr::mut_ptr::<impl *mut T>::offset (5 samples, 0.30%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (79 samples, 4.68%)<core..core::slice::iter::Iter<T>::post_inc_start (24 samples, 1.42%)core::ptr::non_null::NonNull<T>::new_unchecked (3 samples, 0.18%)<core::iter::adapters::copied::Copied<I> as core::iter::traits::iterator::Iterator>::next (132 samples, 7.82%)<core::iter..core::option::Option<&T>::copied (38 samples, 2.25%)c..<core::option::Option<T> as core::ops::try_trait::Try>::branch (12 samples, 0.71%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (250 samples, 14.80%)<core::iter::adapters::..core::option::Option<T>::or_else (217 samples, 12.85%)core::option::Optio..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next::{{closure}} (195 samples, 11.55%)<core::iter::adap..core::option::Option<T>::as_mut (5 samples, 0.30%)core::option::Option<T>::expect (18 samples, 1.07%)core::result::Result<T,E>::ok (36 samples, 2.13%)c..heapless::vec::Vec<T,_>::new (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)heapless::vec::Vec<T,_>::capacity (3 samples, 0.18%)core::mem::maybe_uninit::MaybeUninit<T>::new (28 samples, 1.66%)core::mem::manually_drop::ManuallyDrop<T>::new (1 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.12%)core::slice::<impl [T]>::get_unchecked_mut (31 samples, 1.84%)c..<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (18 samples, 1.07%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (5 samples, 0.30%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::to_bytes (532 samples, 31.50%)<tftp::packet::DataPacket as tftp::packet::ByteConv..core::iter::traits::iterator::Iterator::collect (532 samples, 31.50%)core::iter::traits::iterator::Iterator::collect<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (532 samples, 31.50%)<heapless::vec::Vec<T,_> as core::iter::traits::col..heapless::vec::Vec<T,_>::push (150 samples, 8.88%)heapless::vec..heapless::vec::Vec<T,_>::push_unchecked (126 samples, 7.46%)heapless::..heapless::vec::Vec<T,_>::is_full (12 samples, 0.71%)heapless::vec::Vec<T,_>::capacity (3 samples, 0.18%)core::iter::traits::iterator::Iterator::chain (1 samples, 0.06%)core::iter::adapters::chain::Chain<A,B>::new (1 samples, 0.06%)memcpy (1 samples, 0.06%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (6 samples, 0.36%)core::option::Option<T>::as_mut (1 samples, 0.06%)core::iter::adapters::chain::and_then_or_clear (26 samples, 1.54%)core::ptr::drop_in_place<core::option::Option<core::array::iter::IntoIter<u8,2_usize>>> (1 samples, 0.06%)core::ptr::drop_in_place<core::array::iter::IntoIter<u8,2_usize>> (1 samples, 0.06%)<core::array::iter::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.06%)core::array::iter::IntoIter<T,_>::as_mut_slice (1 samples, 0.06%)core::slice::<impl [T]>::get_unchecked_mut (1 samples, 0.06%)<core::ops::index_range::IndexRange as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.06%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (19 samples, 1.12%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (52 samples, 3.08%)<he..heapless::vec::Vec<T,_>::as_slice (47 samples, 2.78%)he..core::slice::raw::from_raw_parts (40 samples, 2.37%)co..core::ptr::slice_from_raw_parts (33 samples, 1.95%)c..core::ptr::metadata::from_raw_parts (32 samples, 1.89%)c..core::ptr::const_ptr::<impl *const T>::read (29 samples, 1.72%)core::ptr::read (22 samples, 1.30%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.18%)<heapless::vec::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (157 samples, 9.30%)<heapless::ve..core::slice::<impl [T]>::get_unchecked_mut (23 samples, 1.36%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (17 samples, 1.01%)core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::offset (2 samples, 0.12%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (309 samples, 18.29%)<core::iter::adapters::chain:..core::option::Option<T>::or_else (267 samples, 15.81%)core::option::Option<T>:..<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next::{{closure}} (236 samples, 13.97%)<core::iter::adapters..core::option::Option<T>::as_mut (17 samples, 1.01%)core::option::Option<T>::expect (26 samples, 1.54%)core::result::Result<T,E>::ok (26 samples, 1.54%)heapless::vec::Vec<T,_>::capacity (9 samples, 0.53%)core::mem::maybe_uninit::MaybeUninit<T>::new (27 samples, 1.60%)core::mem::manually_drop::ManuallyDrop<T>::new (2 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::add (6 samples, 0.36%)core::ptr::mut_ptr::<impl *mut T>::offset (4 samples, 0.24%)core::slice::<impl [T]>::get_unchecked_mut (38 samples, 2.25%)c..<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (24 samples, 1.42%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (8 samples, 0.47%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (1,143 samples, 67.67%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytescore::iter::traits::iterator::Iterator::collect (610 samples, 36.12%)core::iter::traits::iterator::Iterator::collect<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (610 samples, 36.12%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::Fr..heapless::vec::Vec<T,_>::push (179 samples, 10.60%)heapless::vec::..heapless::vec::Vec<T,_>::push_unchecked (139 samples, 8.23%)heapless::v..heapless::vec::Vec<T,_>::is_full (16 samples, 0.95%)heapless::vec::Vec<T,_>::capacity (4 samples, 0.24%)core::ptr::const_ptr::<impl *const T>::is_null (8 samples, 0.47%)core::ptr::const_ptr::<impl *const T>::is_null::runtime_impl (4 samples, 0.24%)core::ptr::const_ptr::<impl *const T>::addr (2 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::is_null (3 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (2 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::addr (2 samples, 0.12%)core::ptr::mut_ptr::<impl *mut T>::add (19 samples, 1.12%)core::ptr::mut_ptr::<impl *mut T>::offset (19 samples, 1.12%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (72 samples, 4.26%)<core..core::slice::iter::Iter<T>::post_inc_start (47 samples, 2.78%)co..core::ptr::non_null::NonNull<T>::new_unchecked (3 samples, 0.18%)core::clone::impls::<impl core::clone::Clone for u8>::clone (7 samples, 0.41%)heapless::vec::Vec<T,_>::new (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)core::mem::maybe_uninit::MaybeUninit<T>::new (28 samples, 1.66%)core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::offset (3 samples, 0.18%)core::slice::<impl [T]>::get_unchecked_mut (22 samples, 1.30%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (18 samples, 1.07%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (3 samples, 0.18%)<heapless::vec::Vec<T,_> as core::clone::Clone>::clone (261 samples, 15.45%)<heapless::vec::Vec<T,_>..heapless::vec::Vec<T,_>::clone (261 samples, 15.45%)heapless::vec::Vec<T,_>:..heapless::vec::Vec<T,_>::push_unchecked (123 samples, 7.28%)heapless::..heapless::vec::Vec<T,_>::is_full (20 samples, 1.18%)heapless::vec::Vec<T,_>::capacity (6 samples, 0.36%)core::result::Result<T,E>::map (1 samples, 0.06%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next::{{closure}} (1 samples, 0.06%)core::option::Option<T>::map (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)arrayvec::arrayvec::ArrayVec<T,_>::try_push (1 samples, 0.06%)arrayvec::arrayvec_impl::ArrayVecImpl::try_push (1 samples, 0.06%)arrayvec::arrayvec_impl::ArrayVecImpl::push_unchecked (1 samples, 0.06%)core::ptr::write (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (1 samples, 0.06%)tftp::map::Map<K,V,_>::insert (4 samples, 0.24%)tftp::map::Map<K,V,_>::remove (2 samples, 0.12%)tftp::map::Map<K,V,_>::iter (1 samples, 0.06%)<&tftp::map::Map<K,V,_> as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.06%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.06%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (1 samples, 0.06%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (1 samples, 0.06%)<arrayvec::arrayvec::ArrayVec<T,_> as arrayvec::arrayvec_impl::ArrayVecImpl>::len (1 samples, 0.06%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.06%)<heapless::vec::Vec<T,_> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.06%)heapless::vec::Vec<T,_>::as_mut_slice (1 samples, 0.06%)<std::fs::File as std::io::Read>::read (1 samples, 0.06%)std::sys::unix::fs::File::read (1 samples, 0.06%)std::sys::unix::fd::FileDesc::read (1 samples, 0.06%)read (1 samples, 0.06%)<tftp::io::StdCompatFile as tftp::std_compat::io::Read>::read (2 samples, 0.12%)core::result::Result<T,E>::map_err (1 samples, 0.06%)__rust_probestack (1 samples, 0.06%)heapless::vec::Vec<T,_>::new (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)core::result::Result<T,E>::ok (21 samples, 1.24%)heapless::vec::Vec<T,_>::capacity (4 samples, 0.24%)core::mem::maybe_uninit::MaybeUninit<T>::new (38 samples, 2.25%)c..core::mem::manually_drop::ManuallyDrop<T>::new (3 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::add (3 samples, 0.18%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.06%)core::slice::<impl [T]>::get_unchecked_mut (22 samples, 1.30%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (15 samples, 0.89%)core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr (1 samples, 0.06%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::next (474 samples, 28.06%)<tftp::storage::FileReader<T> as tftp::storag..tftp::storage::FileReader<T>::read_block (208 samples, 12.31%)tftp::storage::Fil..heapless::vec::Vec<T,_>::resize (202 samples, 11.96%)heapless::vec::Vec..heapless::vec::Vec<T,_>::push (167 samples, 9.89%)heapless::vec:..heapless::vec::Vec<T,_>::push_unchecked (145 samples, 8.58%)heapless::ve..heapless::vec::Vec<T,_>::is_full (22 samples, 1.30%)heapless::vec::Vec<T,_>::capacity (7 samples, 0.41%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.06%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (2 samples, 0.12%)tftp::packet::PacketType::from_bytes (2 samples, 0.12%)tftp::packet::try_from (2 samples, 0.12%)core::slice::<impl [T]>::get (1 samples, 0.06%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.06%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.06%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.06%)core::result::Result<T,E>::map (1 samples, 0.06%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from::{{closure}} (1 samples, 0.06%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (2 samples, 0.12%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (2 samples, 0.12%)alloc::vec::Vec<T,A>::extend_desugared (2 samples, 0.12%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.06%)core::iter::traits::iterator::Iterator::find (1 samples, 0.06%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (1 samples, 0.06%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.06%)core::iter::adapters::map::map_try_fold::{{closure}} (1 samples, 0.06%)core::iter::traits::iterator::Iterator::find::check::{{closure}} (1 samples, 0.06%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.06%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.12%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (2 samples, 0.12%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.06%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (33 samples, 1.95%)<..polling::Poller::wait (32 samples, 1.89%)p..polling::epoll::Poller::wait (30 samples, 1.78%)p..epoll_wait (22 samples, 1.30%)core::result::Result<T,E>::map_err (1 samples, 0.06%)<core::option::IntoIter<A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.06%)<core::option::Item<A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.06%)core::option::Option<T>::take (1 samples, 0.06%)core::mem::replace (1 samples, 0.06%)core::ptr::write (1 samples, 0.06%)sendto (4 samples, 0.24%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (7 samples, 0.41%)std::net::udp::UdpSocket::send_to (6 samples, 0.36%)std::sys_common::net::UdpSocket::send_to (5 samples, 0.30%)std::sys::unix::cvt (1 samples, 0.06%)<isize as std::sys::unix::IsMinusOne>::is_minus_one (1 samples, 0.06%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (1 samples, 0.06%)core::ptr::const_ptr::<impl *const T>::sub_ptr (1 samples, 0.06%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.06%)<arrayvec::arrayvec::Drain<T,_> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.24%)core::option::Option<T>::map (3 samples, 0.18%)<arrayvec::arrayvec::Drain<T,_> as core::iter::traits::iterator::Iterator>::next::{{closure}} (3 samples, 0.18%)core::ptr::read (3 samples, 0.18%)[libc.so.6] (3 samples, 0.18%)arrayvec::arrayvec::ArrayVec<T,_>::drain (1 samples, 0.06%)core::option::Option<T>::and_then (8 samples, 0.47%)tftp::map::Map<K,V,_>::remove::{{closure}} (8 samples, 0.47%)arrayvec::arrayvec::ArrayVec<T,_>::pop_at (8 samples, 0.47%)core::ptr::drop_in_place<arrayvec::arrayvec::Drain<(u64,tftp::storage::TimedBlock),64_usize>> (3 samples, 0.18%)<arrayvec::arrayvec::Drain<T,_> as core::ops::drop::Drop>::drop (3 samples, 0.18%)core::intrinsics::copy (3 samples, 0.18%)[libc.so.6] (3 samples, 0.18%)<tftp::storage::FileReader<T> as tftp::storage::BlockReader>::free_block (10 samples, 0.59%)tftp::map::Map<K,V,_>::remove (10 samples, 0.59%)tftp::map::Map<K,V,_>::iter (1 samples, 0.06%)<&tftp::map::Map<K,V,_> as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.06%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.06%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (1 samples, 0.06%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (1 samples, 0.06%)<arrayvec::arrayvec::ArrayVec<T,_> as arrayvec::arrayvec_impl::ArrayVecImpl>::len (1 samples, 0.06%)core::ptr::drop_in_place<tftp::storage::Block> (1 samples, 0.06%)core::ptr::drop_in_place<heapless::vec::Vec<u8,1416_usize>> (1 samples, 0.06%)<heapless::vec::Vec<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.06%)heapless::vec::Vec<T,_>::as_mut_slice (1 samples, 0.06%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.06%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.06%)core::time::Duration::from_millis (1 samples, 0.06%)core::time::Duration::new (1 samples, 0.06%)core::num::<impl u64>::checked_add (1 samples, 0.06%)log::max_level (1 samples, 0.06%)core::sync::atomic::AtomicUsize::load (1 samples, 0.06%)core::sync::atomic::atomic_load (1 samples, 0.06%)tftp::flow_control::RateControl::start_rtt (1 samples, 0.06%)tftp::std_compat::time::Instant::elapsed (1 samples, 0.06%)core::ops::function::FnOnce::call_once (1 samples, 0.06%)tftp::instant_callback::{{closure}} (1 samples, 0.06%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.06%)clock_gettime (1 samples, 0.06%)__vdso_clock_gettime (1 samples, 0.06%)[[vdso]] (1 samples, 0.06%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.06%)clock_gettime (1 samples, 0.06%)__vdso_clock_gettime (1 samples, 0.06%)tftp::client::client::send_file (64 samples, 3.79%)tftp..tftp::std_compat::time::Instant::elapsed (2 samples, 0.12%)core::ops::function::FnOnce::call_once (2 samples, 0.12%)tftp::instant_callback::{{closure}} (2 samples, 0.12%)std::time::SystemTime::duration_since (1 samples, 0.06%)std::sys::unix::time::SystemTime::sub_time (1 samples, 0.06%)std::sys::unix::time::Timespec::sub_timespec (1 samples, 0.06%)core::time::Duration::new (1 samples, 0.06%)[unknown] (1,682 samples, 99.59%)[unknown]tftp::main (1 samples, 0.06%)clap::derive::Parser::parse (1 samples, 0.06%)<tftp::cli::Args as clap::derive::FromArgMatches>::from_arg_matches_mut (1 samples, 0.06%)clap::parser::matches::arg_matches::ArgMatches::remove_one (1 samples, 0.06%)clap::parser::matches::arg_matches::ArgMatches::try_remove_one (1 samples, 0.06%)core::ptr::drop_in_place<core::iter::adapters::map::Map<core::iter::adapters::flatten::Flatten<alloc::vec::into_iter::IntoIter<alloc::vec::Vec<clap::parser::matches::any_value::AnyValue>>>,clap::parser::matches::arg_matches::unwrap_downcast_into<heapless::string::String<140_usize>>>> (1 samples, 0.06%)core::ptr::drop_in_place<core::iter::adapters::flatten::Flatten<alloc::vec::into_iter::IntoIter<alloc::vec::Vec<clap::parser::matches::any_value::AnyValue>>>> (1 samples, 0.06%)core::ptr::drop_in_place<core::iter::adapters::flatten::FlattenCompat<alloc::vec::into_iter::IntoIter<alloc::vec::Vec<clap::parser::matches::any_value::AnyValue>>,alloc::vec::into_iter::IntoIter<clap::parser::matches::any_value::AnyValue>>> (1 samples, 0.06%)core::ptr::drop_in_place<core::iter::adapters::fuse::Fuse<alloc::vec::into_iter::IntoIter<alloc::vec::Vec<clap::parser::matches::any_value::AnyValue>>>> (1 samples, 0.06%)core::ptr::drop_in_place<core::option::Option<alloc::vec::into_iter::IntoIter<alloc::vec::Vec<clap::parser::matches::any_value::AnyValue>>>> (1 samples, 0.06%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<alloc::vec::Vec<clap::parser::matches::any_value::AnyValue>>> (1 samples, 0.06%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.06%)alloc::vec::into_iter::IntoIter<T,A>::as_raw_mut_slice (1 samples, 0.06%)<&mut I as core::iter::traits::exact_size::ExactSizeIterator>::len (1 samples, 0.06%)core::iter::traits::exact_size::ExactSizeIterator::len (1 samples, 0.06%)<core::option::Option<T> as core::cmp::PartialEq>::eq (1 samples, 0.06%)<T as core::option::SpecOptionPartialEq>::eq (1 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialEq for usize>::eq (1 samples, 0.06%)all (1,689 samples, 100%)tftp (1,689 samples, 100.00%)tftp_start (1 samples, 0.06%)__libc_start_main (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)main (1 samples, 0.06%)std::rt::lang_start (1 samples, 0.06%)std::rt::lang_start_internal (1 samples, 0.06%)std::panic::catch_unwind (1 samples, 0.06%)std::panicking::try (1 samples, 0.06%)std::panicking::try::do_call (1 samples, 0.06%)std::rt::lang_start_internal::{{closure}} (1 samples, 0.06%)std::rt::init (1 samples, 0.06%)std::sys::unix::thread::guard::init (1 samples, 0.06%)std::sys::unix::thread::guard::get_stack_start_aligned (1 samples, 0.06%)std::sys::unix::thread::guard::get_stack_start (1 samples, 0.06%)pthread_getattr_np (1 samples, 0.06%)__isoc99_sscanf (1 samples, 0.06%)[libc.so.6] (1 samples, 0.06%)_IO_sputbackc (1 samples, 0.06%) \ No newline at end of file diff --git a/info/sender_window_size_delayed_encryption.png b/info/sender_window_size_delayed_encryption.png new file mode 100644 index 0000000..8e19ae9 Binary files /dev/null and b/info/sender_window_size_delayed_encryption.png differ diff --git a/info/sender_window_size_delayed_encryption_stack.png b/info/sender_window_size_delayed_encryption_stack.png new file mode 100644 index 0000000..8494edd Binary files /dev/null and b/info/sender_window_size_delayed_encryption_stack.png differ diff --git a/info/sender_window_size_no_encryption_alloc.png b/info/sender_window_size_no_encryption_alloc.png new file mode 100644 index 0000000..b6b064c Binary files /dev/null and b/info/sender_window_size_no_encryption_alloc.png differ diff --git a/info/sender_window_size_no_encryption_stack.png b/info/sender_window_size_no_encryption_stack.png new file mode 100644 index 0000000..787cc51 Binary files /dev/null and b/info/sender_window_size_no_encryption_stack.png differ diff --git a/info/server_flamegraph.svg b/info/server_flamegraph.svg new file mode 100644 index 0000000..11f3678 --- /dev/null +++ b/info/server_flamegraph.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [ld-linux-x86-64.so.2] (8 samples, 0.35%)[ld-linux-x86-64.so.2] (3 samples, 0.13%)[ld-linux-x86-64.so.2] (2 samples, 0.09%)[ld-linux-x86-64.so.2] (2 samples, 0.09%)[ld-linux-x86-64.so.2] (2 samples, 0.09%)[ld-linux-x86-64.so.2] (1 samples, 0.04%)<tftp::cli::Commands as clap::derive::Subcommand>::augment_subcommands (1 samples, 0.04%)clap::builder::command::Command::arg (1 samples, 0.04%)clap::parser::parser::Parser::get_matches_with (1 samples, 0.04%)clap::parser::parser::Parser::parse_subcommand (1 samples, 0.04%)clap::builder::command::Command::_build_subcommand (1 samples, 0.04%)clap::builder::command::Command::_build_self (1 samples, 0.04%)clap::builder::debug_asserts::assert_app (1 samples, 0.04%)clap::builder::command::Command::two_args_of (1 samples, 0.04%)clap::builder::command::two_elements_of (1 samples, 0.04%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)polling::epoll::Poller::ctl (1 samples, 0.04%)epoll_ctl (1 samples, 0.04%)[unknown] (1 samples, 0.04%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 0.09%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (2 samples, 0.09%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)core::slice::<impl [T]>::get (1 samples, 0.04%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (5 samples, 0.22%)tftp::packet::PacketType::from_bytes (1 samples, 0.04%)tftp::packet::try_from (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.04%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (2 samples, 0.09%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (1 samples, 0.04%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.04%)core::result::Result<T,E>::unwrap_unchecked (1 samples, 0.04%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 0.09%)log::max_level (1 samples, 0.04%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)polling::Poller::modify (5 samples, 0.22%)polling::epoll::Poller::modify (5 samples, 0.22%)polling::epoll::Poller::ctl (2 samples, 0.09%)core::option::Option<T>::map (2 samples, 0.09%)polling::epoll::Poller::ctl::{{closure}} (1 samples, 0.04%)polling::epoll::read_flags (1 samples, 0.04%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::iter::traits::iterator::Iterator::find (1 samples, 0.04%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.04%)<core::ops::control_flow::ControlFlow<B,C> as core::ops::try_trait::FromResidual>::from_residual (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (2 samples, 0.09%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (2 samples, 0.09%)alloc::vec::Vec<T,A>::extend_desugared (2 samples, 0.09%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::ptr (1 samples, 0.04%)core::ptr::unique::Unique<T>::as_ptr (1 samples, 0.04%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.04%)<std::sync::mutex::MutexGuard<T> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::time::Duration::from_secs (2 samples, 0.09%)core::time::Duration::new (2 samples, 0.09%)core::num::<impl u64>::checked_add (1 samples, 0.04%)epoll_wait (13 samples, 0.56%)log::max_level (1 samples, 0.04%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)polling::epoll::Poller::modify (1 samples, 0.04%)polling::epoll::Poller::ctl (1 samples, 0.04%)read (1 samples, 0.04%)polling::epoll::Poller::wait (25 samples, 1.08%)std::io::error::Error::last_os_error (3 samples, 0.13%)std::sys::unix::os::errno (2 samples, 0.09%)polling::Poller::wait (30 samples, 1.30%)std::sync::mutex::Mutex<T>::try_lock (1 samples, 0.04%)std::sync::mutex::MutexGuard<T>::new (1 samples, 0.04%)std::sync::poison::Flag::guard (1 samples, 0.04%)recvfrom (1 samples, 0.04%)<isize as std::sys::unix::IsMinusOne>::is_minus_one (1 samples, 0.04%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (43 samples, 1.86%)<..std::net::udp::UdpSocket::recv_from (5 samples, 0.22%)std::sys_common::net::UdpSocket::recv_from (4 samples, 0.17%)std::sys::unix::net::Socket::recv_from (4 samples, 0.17%)std::sys::unix::net::Socket::recv_from_with_flags (3 samples, 0.13%)std::sys::unix::cvt (2 samples, 0.09%)std::io::error::Error::last_os_error (1 samples, 0.04%)std::io::error::Error::from_raw_os_error (1 samples, 0.04%)std::io::error::repr_bitpacked::Repr::new_os (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<std::net::socket_addr::SocketAddr as core::cmp::Ord>::cmp (2 samples, 0.09%)<std::net::socket_addr::SocketAddrV4 as core::cmp::Ord>::cmp (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::Ord for u16>::cmp (1 samples, 0.04%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut,K,V,Type>::into_leaf (1 samples, 0.04%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut,K,V,Type>::keys (2 samples, 0.09%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::entry (7 samples, 0.30%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (6 samples, 0.26%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (6 samples, 0.26%)alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (6 samples, 0.26%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.04%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.04%)<alloc::vec::ExtendElement<T> as alloc::vec::ExtendWith<T>>::next (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::needs_to_grow (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_with (6 samples, 0.26%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)core::mem::replace (1 samples, 0.04%)alloc::vec::Vec<T,A>::resize (8 samples, 0.35%)alloc::vec::Vec<T,A>::truncate (1 samples, 0.04%)core::cmp::PartialOrd::gt (1 samples, 0.04%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for u64>::partial_cmp (1 samples, 0.04%)core::ptr::drop_in_place<core::result::Result<(usize,std::net::socket_addr::SocketAddr),std::io::error::Error>> (1 samples, 0.04%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.04%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.04%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.04%)core::ptr::drop_in_place<std::io::error::ErrorData<alloc::boxed::Box<std::io::error::Custom>>> (1 samples, 0.04%)core::time::Duration::from_millis (1 samples, 0.04%)log::max_level (3 samples, 0.13%)core::sync::atomic::AtomicUsize::load (2 samples, 0.09%)core::sync::atomic::atomic_load (1 samples, 0.04%)std::time::Instant::elapsed (1 samples, 0.04%)std::time::Instant::now (1 samples, 0.04%)std::sys::unix::time::inner::Instant::now (1 samples, 0.04%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.04%)clock_gettime (1 samples, 0.04%)__vdso_clock_gettime (1 samples, 0.04%)[[vdso]] (1 samples, 0.04%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (2 samples, 0.09%)clock_gettime (2 samples, 0.09%)__vdso_clock_gettime (2 samples, 0.09%)[[vdso]] (1 samples, 0.04%)tftp::instant_callback (3 samples, 0.13%)std::time::Instant::now (1 samples, 0.04%)std::sys::unix::time::inner::Instant::now (1 samples, 0.04%)core::ptr::drop_in_place<(core::result::Result<tftp::packet::PacketType,tftp::error::PacketError>,tftp::encryption::EncryptionLevel,&core::option::Option<tftp::encryption::Encryptor>)> (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (2 samples, 0.09%)chacha20::xchacha::hchacha (2 samples, 0.09%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (4 samples, 0.17%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (4 samples, 0.17%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)aead::Buffer::len (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::convert::AsRef<[T]>>::as_ref (1 samples, 0.04%)core::slice::<impl [T]>::split_at_mut (1 samples, 0.04%)tftp::encryption::Encryptor::decrypt (7 samples, 0.30%)aead::AeadInPlace::decrypt_in_place (7 samples, 0.30%)generic_array::GenericArray<T,N>::from_slice (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)tftp::server::connection::Connection<R,W,S>::receive_packet (11 samples, 0.48%)tftp::packet::PacketType::from_bytes (3 samples, 0.13%)tftp::packet::try_from (2 samples, 0.09%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)[libc.so.6] (2 samples, 0.09%)tftp::server::server::send_data_blocks (4 samples, 0.17%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain (3 samples, 0.13%)alloc::collections::btree::map::BTreeMap<K,V,A>::drain_filter (3 samples, 0.13%)alloc::collections::btree::map::BTreeMap<K,V,A>::drain_filter_inner (1 samples, 0.04%)<alloc::alloc::Global as core::clone::Clone>::clone (1 samples, 0.04%)tftp::main (96 samples, 4.16%)tftp:..tftp::server::server::server (96 samples, 4.16%)tftp:..tftp::server::server::write_block (2 samples, 0.09%)log::max_level (1 samples, 0.04%)core::sync::atomic::AtomicUsize::load (1 samples, 0.04%)core::sync::atomic::atomic_load (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (1 samples, 0.04%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (1 samples, 0.04%)tftp::packet::try_from (1 samples, 0.04%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (1 samples, 0.04%)polling::Poller::wait (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_desugared (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.04%)alloc::raw_vec::finish_grow (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.04%)alloc::alloc::Global::alloc_impl (1 samples, 0.04%)core::ptr::non_null::NonNull<[T]>::slice_from_raw_parts (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.13%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (3 samples, 0.13%)core::result::Result<T,E>::map (2 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (7 samples, 0.30%)core::result::Result<T,E>::unwrap (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (2 samples, 0.09%)core::result::Result<T,E>::map (2 samples, 0.09%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (1 samples, 0.04%)core::slice::raw::from_raw_parts (1 samples, 0.04%)chacha20::xchacha::quarter_round (32 samples, 1.39%)core::num::<impl u32>::rotate_left (1 samples, 0.04%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (4 samples, 0.17%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (3 samples, 0.13%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.09%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (2 samples, 0.09%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (2 samples, 0.09%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::cmp::min (1 samples, 0.04%)core::cmp::Ord::min (1 samples, 0.04%)core::cmp::min_by (1 samples, 0.04%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (2 samples, 0.09%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (6 samples, 0.26%)memcpy (1 samples, 0.04%)core::iter::traits::iterator::Iterator::zip (7 samples, 0.30%)core::iter::adapters::zip::Zip<A,B>::new (7 samples, 0.30%)[libc.so.6] (1 samples, 0.04%)core::num::<impl u32>::to_le_bytes (1 samples, 0.04%)core::slice::<impl [T]>::chunks_exact (1 samples, 0.04%)core::slice::iter::ChunksExact<T>::new (1 samples, 0.04%)core::slice::<impl [T]>::split_at_unchecked (1 samples, 0.04%)core::slice::<impl [T]>::chunks_exact_mut (2 samples, 0.09%)core::slice::iter::ChunksExactMut<T>::new (1 samples, 0.04%)core::slice::<impl [T]>::copy_from_slice (2 samples, 0.09%)core::intrinsics::copy_nonoverlapping (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.04%)core::iter::adapters::enumerate::Enumerate<I>::new (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (7 samples, 0.30%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (3 samples, 0.13%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (3 samples, 0.13%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.04%)chacha20::xchacha::hchacha (77 samples, 3.34%)cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (15 samples, 0.65%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (15 samples, 0.65%)core::iter::traits::iterator::Iterator::for_each (14 samples, 0.61%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (13 samples, 0.56%)core::iter::traits::iterator::Iterator::fold (13 samples, 0.56%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.17%)core::slice::iter::IterMut<T>::post_inc_start (2 samples, 0.09%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.09%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (6 samples, 0.26%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (6 samples, 0.26%)core::iter::traits::iterator::Iterator::fold (6 samples, 0.26%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (5 samples, 0.22%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (4 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (4 samples, 0.17%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.04%)<u8 as core::default::Default>::default (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (94 samples, 4.07%)<cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (8 samples, 0.35%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (8 samples, 0.35%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (13 samples, 0.56%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (8 samples, 0.35%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (7 samples, 0.30%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (2 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (119 samples, 5.16%)<ciphe..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (25 samples, 1.08%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (25 samples, 1.08%)core::iter::traits::iterator::Iterator::for_each (25 samples, 1.08%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (25 samples, 1.08%)core::iter::traits::iterator::Iterator::fold (25 samples, 1.08%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.22%)core::slice::iter::IterMut<T>::post_inc_start (2 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.04%)core::num::<impl u64>::to_le_bytes (1 samples, 0.04%)core::num::<impl u64>::to_le (1 samples, 0.04%)core::slice::<impl [T]>::copy_from_slice (2 samples, 0.09%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.13%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.13%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (10 samples, 0.43%)universal_hash::UniversalHash::update (3 samples, 0.13%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (3 samples, 0.13%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (3 samples, 0.13%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (3 samples, 0.13%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (3 samples, 0.13%)poly1305::backend::soft::State::compute_block (3 samples, 0.13%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (3 samples, 0.13%)core::core_arch::x86::sse2::_mm_add_epi32 (77 samples, 3.34%)cor..core::core_arch::x86::m128iExt::as_i32x4 (14 samples, 0.61%)core::core_arch::x86::sse2::_mm_slli_epi32 (75 samples, 3.25%)cor..core::core_arch::x86::m128iExt::as_i32x4 (20 samples, 0.87%)core::core_arch::x86::sse2::_mm_srli_epi32 (12 samples, 0.52%)core::core_arch::x86::m128iExt::as_i32x4 (3 samples, 0.13%)chacha20::backends::sse2::add_xor_rot (388 samples, 16.82%)chacha20::backends::sse2::..core::core_arch::x86::sse2::_mm_xor_si128 (42 samples, 1.82%)c..chacha20::backends::sse2::cols_to_rows (22 samples, 0.95%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (12 samples, 0.52%)core::core_arch::x86::m128iExt::as_i32x4 (4 samples, 0.17%)chacha20::backends::sse2::double_quarter_round (438 samples, 18.99%)chacha20::backends::sse2::doub..chacha20::backends::sse2::rows_to_cols (26 samples, 1.13%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (15 samples, 0.65%)core::core_arch::x86::m128iExt::as_i32x4 (5 samples, 0.22%)core::core_arch::x86::sse2::_mm_add_epi32 (6 samples, 0.26%)<usize as core::iter::range::Step>::forward_unchecked (3 samples, 0.13%)core::num::<impl usize>::unchecked_add (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.09%)core::ptr::read (6 samples, 0.26%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.09%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (2 samples, 0.09%)chacha20::backends::sse2::rounds (483 samples, 20.94%)chacha20::backends::sse2::roundscore::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (25 samples, 1.08%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (23 samples, 1.00%)core::mem::replace (12 samples, 0.52%)core::ptr::write (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_set_epi32 (1 samples, 0.04%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (491 samples, 21.28%)<chacha20::backends::sse2::Backend..core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.22%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (4 samples, 0.17%)core::mem::replace (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)<inout::inout_buf::InOutBufIter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::ptr::write (11 samples, 0.48%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (174 samples, 7.54%)<core::ite..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (120 samples, 5.20%)core::..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (97 samples, 4.20%)<gene..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (11 samples, 0.48%)<u8 as core::default::Default>::default (2 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (16 samples, 0.69%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (7 samples, 0.30%)core::ptr::mut_ptr::<impl *mut T>::addr (5 samples, 0.22%)core::ptr::mut_ptr::<impl *mut T>::add (16 samples, 0.69%)core::ptr::mut_ptr::<impl *mut T>::offset (14 samples, 0.61%)core::iter::traits::iterator::Iterator::for_each (349 samples, 15.13%)core::iter::traits::ite..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (345 samples, 14.95%)<core::iter::adapters::..core::iter::traits::iterator::Iterator::fold (345 samples, 14.95%)core::iter::traits::ite..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (96 samples, 4.16%)<core..core::slice::iter::IterMut<T>::post_inc_start (49 samples, 2.12%)c..core::ptr::non_null::NonNull<T>::new_unchecked (3 samples, 0.13%)_init (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::into_inner (7 samples, 0.30%)core::ptr::read (4 samples, 0.17%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.13%)memcpy (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (359 samples, 15.56%)generic_array::impls::<i..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (359 samples, 15.56%)<generic_array::GenericA..generic_array::ArrayBuilder<T,N>::new (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (84 samples, 3.64%)<gen..core::slice::raw::from_raw_parts (69 samples, 2.99%)cor..core::ptr::slice_from_raw_parts (48 samples, 2.08%)c..core::ptr::metadata::from_raw_parts (46 samples, 1.99%)c..<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (35 samples, 1.52%)core::slice::raw::from_raw_parts_mut (27 samples, 1.17%)core::ptr::slice_from_raw_parts_mut (20 samples, 0.87%)core::ptr::metadata::from_raw_parts_mut (18 samples, 0.78%)<usize as core::iter::range::Step>::forward_unchecked (16 samples, 0.69%)core::num::<impl usize>::unchecked_add (2 samples, 0.09%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (11 samples, 0.48%)core::ptr::read (28 samples, 1.21%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (5 samples, 0.22%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (4 samples, 0.17%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (113 samples, 4.90%)core::..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (103 samples, 4.46%)<core..core::mem::replace (50 samples, 2.17%)c..core::ptr::write (5 samples, 0.22%)[libc.so.6] (1 samples, 0.04%)core::ptr::read (3 samples, 0.13%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.04%)core::iter::adapters::enumerate::Enumerate<I>::new (1 samples, 0.04%)core::ptr::write (8 samples, 0.35%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (164 samples, 7.11%)<core::ite..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (105 samples, 4.55%)core:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (85 samples, 3.68%)<gen..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (17 samples, 0.74%)<u8 as core::default::Default>::default (7 samples, 0.30%)core::ptr::mut_ptr::<impl *mut T>::is_null (16 samples, 0.69%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (9 samples, 0.39%)core::ptr::mut_ptr::<impl *mut T>::addr (3 samples, 0.13%)core::ptr::mut_ptr::<impl *mut T>::add (14 samples, 0.61%)core::ptr::mut_ptr::<impl *mut T>::offset (14 samples, 0.61%)core::ptr::non_null::NonNull<T>::as_ptr (2 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each (314 samples, 13.61%)core::iter::traits::i..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (313 samples, 13.57%)<core::iter::adapter..core::iter::traits::iterator::Iterator::fold (311 samples, 13.48%)core::iter::traits::..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (79 samples, 3.42%)<co..core::slice::iter::IterMut<T>::post_inc_start (39 samples, 1.69%)core::ptr::non_null::NonNull<T>::new_unchecked (4 samples, 0.17%)generic_array::ArrayBuilder<T,N>::into_inner (2 samples, 0.09%)core::ptr::read (1 samples, 0.04%)_init (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.04%)generic_array::ArrayBuilder<T,N>::iter_position (3 samples, 0.13%)core::slice::<impl [T]>::iter_mut (1 samples, 0.04%)core::slice::iter::IterMut<T>::new (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (1,544 samples, 66.93%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,544 samples, 66.93%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1,544 samples, 66.93%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backendchacha20::backends::sse2::inner (1,543 samples, 66.88%)chacha20::backends::sse2::inner<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (1,540 samples, 66.75%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::callinout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (689 samples, 29.87%)inout::inout::InOut<generic_array::GenericArray<..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (321 samples, 13.91%)generic_array::impls:..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (321 samples, 13.91%)<generic_array::Gener..generic_array::ArrayBuilder<T,N>::new (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_slli_epi32 (4 samples, 0.17%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_srli_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)chacha20::backends::sse2::add_xor_rot (18 samples, 0.78%)core::core_arch::x86::sse2::_mm_xor_si128 (3 samples, 0.13%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (20 samples, 0.87%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (22 samples, 0.95%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (21 samples, 0.91%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (21 samples, 0.91%)chacha20::backends::sse2::inner (21 samples, 0.91%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (21 samples, 0.91%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (21 samples, 0.91%)chacha20::backends::sse2::rounds (21 samples, 0.91%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.04%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (6 samples, 0.26%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.22%)core::mem::replace (2 samples, 0.09%)core::ptr::read (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::offset (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (1,581 samples, 68.53%)cipher::stream::StreamCipher::apply_keystreamcipher::stream::StreamCipher::try_apply_keystream (1,581 samples, 68.53%)cipher::stream::StreamCipher::try_apply_keystream<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (1,581 samples, 68.53%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inoutinout::inout_buf::InOutBuf<u8>::xor_in2out (13 samples, 0.56%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::offset (2 samples, 0.09%)zeroize::atomic_fence (1 samples, 0.04%)core::sync::atomic::compiler_fence (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (7 samples, 0.30%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (7 samples, 0.30%)core::mem::replace (4 samples, 0.17%)core::ptr::read (2 samples, 0.09%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (10 samples, 0.43%)<[Z] as zeroize::Zeroize>::zeroize (10 samples, 0.43%)zeroize::volatile_set (9 samples, 0.39%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)<&mut I as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (13 samples, 0.56%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (3 samples, 0.13%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (3 samples, 0.13%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (3 samples, 0.13%)<[Z: N] as zeroize::Zeroize>::zeroize (3 samples, 0.13%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (3 samples, 0.13%)<Z as zeroize::Zeroize>::zeroize (2 samples, 0.09%)zeroize::atomic_fence (2 samples, 0.09%)core::sync::atomic::compiler_fence (2 samples, 0.09%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.04%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.09%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (5 samples, 0.22%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (5 samples, 0.22%)core::iter::traits::iterator::Iterator::for_each (4 samples, 0.17%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (4 samples, 0.17%)core::iter::traits::iterator::Iterator::fold (4 samples, 0.17%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.04%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.09%)core::ptr::const_ptr::<impl *const T>::is_null (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (11 samples, 0.48%)<T as core::convert::TryInto<U>>::try_into (100 samples, 4.33%)<T as..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (82 samples, 3.55%)core..core::result::Result<T,E>::map (43 samples, 1.86%)c..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (9 samples, 0.39%)core::ptr::const_ptr::<impl *const T>::cast (2 samples, 0.09%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (12 samples, 0.52%)core::slice::raw::from_raw_parts (8 samples, 0.35%)core::ptr::slice_from_raw_parts (4 samples, 0.17%)core::ptr::metadata::from_raw_parts (2 samples, 0.09%)core::convert::num::<impl core::convert::From<u32> for u64>::from (5 samples, 0.22%)core::num::<impl u32>::from_le_bytes (30 samples, 1.30%)core::num::<impl u32>::from_ne_bytes (8 samples, 0.35%)core::result::Result<T,E>::unwrap (31 samples, 1.34%)core::ptr::const_ptr::<impl *const T>::add (5 samples, 0.22%)core::ptr::const_ptr::<impl *const T>::offset (4 samples, 0.17%)core::ptr::const_ptr::<impl *const [T]>::as_ptr (1 samples, 0.04%)core::ptr::const_ptr::<impl *const T>::cast (5 samples, 0.22%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (337 samples, 14.61%)<universal_hash::Unive..<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (332 samples, 14.39%)<poly1305::backend::so..poly1305::backend::soft::State::compute_block (332 samples, 14.39%)poly1305::backend::sof..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (52 samples, 2.25%)c..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (45 samples, 1.95%)<..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (33 samples, 1.43%)core::ptr::slice_from_raw_parts (16 samples, 0.69%)core::ptr::metadata::from_raw_parts (8 samples, 0.35%)universal_hash::UniversalHash::update (338 samples, 14.65%)universal_hash::Univer..<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (338 samples, 14.65%)<poly1305::Poly1305 as..<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (338 samples, 14.65%)<poly1305::backend::au..poly1305::backend::autodetect::avx2_cpuid::InitToken::get (1 samples, 0.04%)universal_hash::UniversalHash::update_padded (346 samples, 15.00%)universal_hash::Univers..universal_hash::to_blocks (1 samples, 0.04%)core::slice::raw::from_raw_parts (1 samples, 0.04%)<u8 as subtle::ConstantTimeEq>::ct_eq (5 samples, 0.22%)<T as core::convert::Into<U>>::into (5 samples, 0.22%)<subtle::Choice as core::convert::From<u8>>::from (5 samples, 0.22%)subtle::black_box (3 samples, 0.13%)core::ptr::read_volatile (2 samples, 0.09%)core::cmp::min (1 samples, 0.04%)core::cmp::Ord::min (1 samples, 0.04%)core::cmp::min_by (1 samples, 0.04%)core::ops::function::FnOnce::call_once (1 samples, 0.04%)core::iter::traits::iterator::Iterator::zip (3 samples, 0.13%)core::iter::adapters::zip::Zip<A,B>::new (3 samples, 0.13%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (3 samples, 0.13%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (2 samples, 0.09%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::size_hint (2 samples, 0.09%)core::ptr::const_ptr::<impl *const T>::sub_ptr (1 samples, 0.04%)<[T] as subtle::ConstantTimeEq>::ct_eq (9 samples, 0.39%)core::slice::<impl [T]>::iter (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.13%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.04%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (1,964 samples, 85.13%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detacheduniversal_hash::UniversalHash::verify (14 samples, 0.61%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (5 samples, 0.22%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (5 samples, 0.22%)poly1305::backend::soft::State::finalize_mut (5 samples, 0.22%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (4 samples, 0.17%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (4 samples, 0.17%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.04%)core::slice::raw::from_raw_parts_mut (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)core::mem::replace (1 samples, 0.04%)<[Z] as zeroize::Zeroize>::zeroize (3 samples, 0.13%)zeroize::volatile_set (3 samples, 0.13%)core::ptr::write_volatile (1 samples, 0.04%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (2 samples, 0.09%)core::slice::raw::from_raw_parts (2 samples, 0.09%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::result::Result<T,E>::map (1 samples, 0.04%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.04%)<poly1305::backend::soft::State as core::default::Default>::default (1 samples, 0.04%)core::array::<impl core::default::Default for [T: _]>::default (1 samples, 0.04%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (6 samples, 0.26%)poly1305::backend::autodetect::State::new (6 samples, 0.26%)poly1305::backend::soft::State::new (6 samples, 0.26%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.04%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.04%)core::ptr::slice_from_raw_parts (1 samples, 0.04%)core::ptr::metadata::from_raw_parts (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (2 samples, 0.09%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (1 samples, 0.04%)chacha20::backends::sse2::inner (1 samples, 0.04%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (3 samples, 0.13%)core::core_arch::x86::sse2::_mm_slli_epi32 (2 samples, 0.09%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_srli_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)chacha20::backends::sse2::add_xor_rot (18 samples, 0.78%)core::core_arch::x86::sse2::_mm_xor_si128 (1 samples, 0.04%)chacha20::backends::sse2::cols_to_rows (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)chacha20::backends::sse2::double_quarter_round (20 samples, 0.87%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (28 samples, 1.21%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (28 samples, 1.21%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (28 samples, 1.21%)chacha20::backends::sse2::inner (28 samples, 1.21%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (28 samples, 1.21%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (27 samples, 1.17%)chacha20::backends::sse2::rounds (27 samples, 1.17%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (4 samples, 0.17%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.13%)core::mem::replace (1 samples, 0.04%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (2 samples, 0.09%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.04%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::remaining_blocks (1 samples, 0.04%)core::result::Result<T,E>::ok (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (39 samples, 1.69%)cipher::stream::StreamCipher::try_apply_keystream (39 samples, 1.69%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (38 samples, 1.65%)inout::inout_buf::InOutBuf<u8>::xor_in2out (6 samples, 0.26%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)core::mem::replace (2 samples, 0.09%)core::ptr::read (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (5 samples, 0.22%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (5 samples, 0.22%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (4 samples, 0.17%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.04%)tftp::server::connection::Connection<R,W,S>::receive_packet (2,144 samples, 92.93%)tftp::server::connection::Connection<R,W,S>::receive_packettftp::encryption::Encryptor::decrypt (2,144 samples, 92.93%)tftp::encryption::Encryptor::decryptaead::AeadInPlace::decrypt_in_place (2,144 samples, 92.93%)aead::AeadInPlace::decrypt_in_place<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (2,144 samples, 92.93%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detachedchacha20poly1305::cipher::Cipher<C>::new (61 samples, 2.64%)ch..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (11 samples, 0.48%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (11 samples, 0.48%)core::iter::traits::iterator::Iterator::for_each (11 samples, 0.48%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (11 samples, 0.48%)core::iter::traits::iterator::Iterator::fold (11 samples, 0.48%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (4 samples, 0.17%)core::slice::iter::IterMut<T>::post_inc_start (4 samples, 0.17%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.04%)tftp::encryption::InitialKeys::finalize (1 samples, 0.04%)x25519_dalek::x25519::EphemeralSecret::diffie_hellman (1 samples, 0.04%)curve25519_dalek::montgomery::<impl core::ops::arith::Mul<curve25519_dalek::montgomery::MontgomeryPoint> for curve25519_dalek::scalar::Scalar>::mul (1 samples, 0.04%)curve25519_dalek::montgomery::<impl core::ops::arith::Mul<&curve25519_dalek::montgomery::MontgomeryPoint> for &curve25519_dalek::scalar::Scalar>::mul (1 samples, 0.04%)<&curve25519_dalek::montgomery::MontgomeryPoint as core::ops::arith::Mul<&curve25519_dalek::scalar::Scalar>>::mul (1 samples, 0.04%)<T as core::convert::Into<U>>::into (1 samples, 0.04%)<subtle::Choice as core::convert::From<u8>>::from (1 samples, 0.04%)tftp::server::connection::ConnectionBuilder::with_request (2 samples, 0.09%)tftp::server::extensions::create_options (2 samples, 0.09%)tftp::key_management::create_finalized_keys (2 samples, 0.09%)tftp::key_management::create_initial_keys (1 samples, 0.04%)<x25519_dalek::x25519::PublicKey as core::convert::From<&x25519_dalek::x25519::EphemeralSecret>>::from (1 samples, 0.04%)<&curve25519_dalek::edwards::EdwardsBasepointTable as core::ops::arith::Mul<&curve25519_dalek::scalar::Scalar>>::mul (1 samples, 0.04%)curve25519_dalek::edwards::EdwardsBasepointTable::basepoint_mul (1 samples, 0.04%)curve25519_dalek::backend::serial::curve_models::<impl core::ops::arith::Add<&curve25519_dalek::backend::serial::curve_models::AffineNielsPoint> for &curve25519_dalek::edwards::EdwardsPoint>::add (1 samples, 0.04%)<&curve25519_dalek::backend::serial::u64::field::FieldElement51 as core::ops::arith::Add<&curve25519_dalek::backend::serial::u64::field::FieldElement51>>::add (1 samples, 0.04%)<curve25519_dalek::backend::serial::u64::field::FieldElement51 as core::ops::arith::AddAssign<&curve25519_dalek::backend::serial::u64::field::FieldElement51>>::add_assign (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)<usize as core::iter::range::Step>::forward_unchecked (1 samples, 0.04%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain::{{closure}} (2 samples, 0.09%)tftp::server::server::send_data_blocks::{{closure}} (2 samples, 0.09%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.09%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::Edge>::right_kv (3 samples, 0.13%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::KV>::new_kv (1 samples, 0.04%)alloc::collections::btree::navigate::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>>::next_kv (5 samples, 0.22%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::forget_node_type (2 samples, 0.09%)tftp::server::server::send_data_blocks (10 samples, 0.43%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain (10 samples, 0.43%)core::ptr::drop_in_place<alloc::collections::btree::map::DrainFilter<std::net::socket_addr::SocketAddr,tftp::server::connection::Connection<std::fs::File,std::fs::File,tftp::socket::StdSocket>,alloc::collections::btree::map::BTreeMap<std::net::socket_addr::SocketAddr,tftp::server::connection::Connection<std::fs::File,std::fs::File,tftp::socket::StdSocket>>::retain<tftp::server::server::send_data_blocks<std::fs::File,std::fs::File,tftp::socket::StdSocket>::{{closure}}>::{{closure}}>> (10 samples, 0.43%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::ops::drop::Drop>::drop (10 samples, 0.43%)core::iter::traits::iterator::Iterator::for_each (10 samples, 0.43%)core::iter::traits::iterator::Iterator::fold (10 samples, 0.43%)<&mut I as core::iter::traits::iterator::Iterator>::next (10 samples, 0.43%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::iter::traits::iterator::Iterator>::next (10 samples, 0.43%)alloc::collections::btree::map::DrainFilterInner<K,V>::next (10 samples, 0.43%)alloc::collections::btree::navigate::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,alloc::collections::btree::node::marker::KV>>::next_leaf_edge (1 samples, 0.04%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,Type>::force (1 samples, 0.04%)alloc::collections::btree::map::BTreeMap<K,V,A>::get (1 samples, 0.04%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (1 samples, 0.04%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (3 samples, 0.13%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (2 samples, 0.09%)core::option::Option<T>::map (2 samples, 0.09%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (2 samples, 0.09%)core::iter::traits::iterator::Iterator::collect (2 samples, 0.09%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 0.09%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (1 samples, 0.04%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_trusted (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.04%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (1 samples, 0.04%)core::ops::function::Fn::call (1 samples, 0.04%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_trusted (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.04%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (1 samples, 0.04%)core::ops::function::Fn::call (1 samples, 0.04%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (1 samples, 0.04%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (1 samples, 0.04%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (5 samples, 0.22%)core::iter::traits::iterator::Iterator::collect (3 samples, 0.13%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (3 samples, 0.13%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (3 samples, 0.13%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (3 samples, 0.13%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)core::num::<impl usize>::checked_add (1 samples, 0.04%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.04%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (2 samples, 0.09%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (1 samples, 0.04%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.04%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (1 samples, 0.04%)alloc::alloc::dealloc (1 samples, 0.04%)cfree (1 samples, 0.04%)<alloc::vec::Vec<u8> as aead::Buffer>::extend_from_slice (1 samples, 0.04%)alloc::vec::Vec<T,A>::extend_from_slice (1 samples, 0.04%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<&T,core::slice::iter::Iter<T>>>::spec_extend (1 samples, 0.04%)alloc::vec::Vec<T,A>::append_elements (1 samples, 0.04%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (1 samples, 0.04%)alloc::raw_vec::RawVec<T,A>::grow_amortized (1 samples, 0.04%)core::cmp::max (1 samples, 0.04%)core::cmp::Ord::max (1 samples, 0.04%)core::cmp::max_by (1 samples, 0.04%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.04%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.04%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.04%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.04%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.04%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.04%)<T as core::convert::TryInto<U>>::try_into (2 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.04%)core::num::<impl u32>::rotate_left (1 samples, 0.04%)chacha20::xchacha::quarter_round (3 samples, 0.13%)core::num::<impl u32>::wrapping_add (1 samples, 0.04%)core::slice::<impl [T]>::chunks_exact (1 samples, 0.04%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (8 samples, 0.35%)chacha20::xchacha::hchacha (7 samples, 0.30%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.04%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (11 samples, 0.48%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.13%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.13%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.13%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.13%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.13%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (3 samples, 0.13%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (3 samples, 0.13%)poly1305::backend::soft::State::finalize_mut (3 samples, 0.13%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (2 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (2 samples, 0.09%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.04%)core::ptr::read (1 samples, 0.04%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.04%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.04%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.04%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.04%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.04%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (2 samples, 0.09%)universal_hash::UniversalHash::update (1 samples, 0.04%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.04%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.04%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (1 samples, 0.04%)poly1305::backend::soft::State::compute_block (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.04%)chacha20::backends::sse2::add_xor_rot (2 samples, 0.09%)core::core_arch::x86::sse2::_mm_slli_epi32 (1 samples, 0.04%)chacha20::backends::sse2::rounds (3 samples, 0.13%)chacha20::backends::sse2::double_quarter_round (3 samples, 0.13%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)cipher::stream::StreamCipher::apply_keystream (4 samples, 0.17%)cipher::stream::StreamCipher::try_apply_keystream (4 samples, 0.17%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (4 samples, 0.17%)cipher::stream_core::StreamCipherCore::write_keystream_block (4 samples, 0.17%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (4 samples, 0.17%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (4 samples, 0.17%)chacha20::backends::sse2::inner (4 samples, 0.17%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (4 samples, 0.17%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (4 samples, 0.17%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.04%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.04%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.04%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (13 samples, 0.56%)universal_hash::UniversalHash::update_padded (4 samples, 0.17%)universal_hash::UniversalHash::update (4 samples, 0.17%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (4 samples, 0.17%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (4 samples, 0.17%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (4 samples, 0.17%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (3 samples, 0.13%)poly1305::backend::soft::State::compute_block (3 samples, 0.13%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.04%)<[Z] as zeroize::Zeroize>::zeroize (1 samples, 0.04%)zeroize::volatile_set (1 samples, 0.04%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.04%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.04%)cipher::stream_core::StreamCipherCore::write_keystream_block (3 samples, 0.13%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.13%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.13%)chacha20::backends::sse2::inner (3 samples, 0.13%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (3 samples, 0.13%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (3 samples, 0.13%)chacha20::backends::sse2::rounds (3 samples, 0.13%)chacha20::backends::sse2::double_quarter_round (3 samples, 0.13%)chacha20::backends::sse2::add_xor_rot (3 samples, 0.13%)core::core_arch::x86::sse2::_mm_slli_epi32 (1 samples, 0.04%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.04%)[unknown] (2,298 samples, 99.61%)[unknown]tftp::server::server::server (2,199 samples, 95.32%)tftp::server::server::servertftp::server::server::write_block (41 samples, 1.78%)t..tftp::server::connection::Connection<R,W,S>::send_packet (38 samples, 1.65%)tftp::encryption::Encryptor::encrypt (30 samples, 1.30%)aead::AeadInPlace::encrypt_in_place (30 samples, 1.30%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (29 samples, 1.26%)chacha20poly1305::cipher::Cipher<C>::new (5 samples, 0.22%)cipher::stream::StreamCipher::apply_keystream (4 samples, 0.17%)cipher::stream::StreamCipher::try_apply_keystream (4 samples, 0.17%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (4 samples, 0.17%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::get_pos (1 samples, 0.04%)all (2,307 samples, 100%)tftp (2,307 samples, 100.00%)tftp_start (1 samples, 0.04%)__libc_start_main (1 samples, 0.04%)[libc.so.6] (1 samples, 0.04%)main (1 samples, 0.04%)std::rt::lang_start (1 samples, 0.04%)std::rt::lang_start_internal (1 samples, 0.04%)std::panic::catch_unwind (1 samples, 0.04%)std::panicking::try (1 samples, 0.04%)std::panicking::try::do_call (1 samples, 0.04%)std::rt::lang_start_internal::{{closure}} (1 samples, 0.04%)std::panic::catch_unwind (1 samples, 0.04%)std::panicking::try (1 samples, 0.04%)std::panicking::try::do_call (1 samples, 0.04%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (1 samples, 0.04%)std::rt::lang_start::{{closure}} (1 samples, 0.04%)std::sys_common::backtrace::__rust_begin_short_backtrace (1 samples, 0.04%)core::ops::function::FnOnce::call_once (1 samples, 0.04%)tftp::main (1 samples, 0.04%)clap::derive::Parser::parse (1 samples, 0.04%)<tftp::cli::Args as clap::derive::FromArgMatches>::from_arg_matches_mut (1 samples, 0.04%)<tftp::cli::Commands as clap::derive::FromArgMatches>::from_arg_matches_mut (1 samples, 0.04%)<tftp::cli::ServerCliConfig as clap::derive::FromArgMatches>::from_arg_matches_mut (1 samples, 0.04%)clap::parser::matches::arg_matches::ArgMatches::remove_one (1 samples, 0.04%)clap::parser::matches::arg_matches::ArgMatches::try_remove_one (1 samples, 0.04%)clap::parser::matches::arg_matches::ArgMatches::try_remove_arg_t (1 samples, 0.04%)clap::util::flat_map::FlatMap<K,V>::remove_entry (1 samples, 0.04%)core::iter::traits::iterator::Iterator::find_map (1 samples, 0.04%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::try_fold (1 samples, 0.04%) \ No newline at end of file diff --git a/info/server_flamegraph_delayed_encryption_stack.svg b/info/server_flamegraph_delayed_encryption_stack.svg new file mode 100644 index 0000000..2fb6939 --- /dev/null +++ b/info/server_flamegraph_delayed_encryption_stack.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch epoll_ctl (1 samples, 0.03%)[unknown] (1 samples, 0.03%)[[stack]] (2 samples, 0.06%)recvfrom (1 samples, 0.03%)[unknown] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (8 samples, 0.25%)[ld-linux-x86-64.so.2] (3 samples, 0.09%)[ld-linux-x86-64.so.2] (2 samples, 0.06%)[ld-linux-x86-64.so.2] (2 samples, 0.06%)[ld-linux-x86-64.so.2] (2 samples, 0.06%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)[ld-linux-x86-64.so.2] (1 samples, 0.03%)core::option::Option<T>::expect (1 samples, 0.03%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (2 samples, 0.06%)core::iter::traits::iterator::Iterator::collect (2 samples, 0.06%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 0.06%)heapless::vec::Vec<T,_>::push (1 samples, 0.03%)heapless::vec::Vec<T,_>::push_unchecked (1 samples, 0.03%)core::slice::<impl [T]>::get_unchecked_mut (1 samples, 0.03%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)<tftp::packet::OptionalAck as tftp::packet::ByteConverter>::to_bytes (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)<tftp::packet::OptionalAck as tftp::packet::ByteConverter>::to_bytes::{{closure}} (1 samples, 0.03%)heapless::vec::Vec<T,_>::extend (1 samples, 0.03%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::option::Option<T>::or_else (1 samples, 0.03%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next::{{closure}} (1 samples, 0.03%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::option::Option<T>::map (1 samples, 0.03%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::next::{{closure}} (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init_read (1 samples, 0.03%)core::ptr::const_ptr::<impl *const T>::read (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::iter::traits::iterator::Iterator::chain (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (6 samples, 0.19%)core::iter::traits::iterator::Iterator::collect (2 samples, 0.06%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 0.06%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::option::Option<T>::or_else (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::new_const (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)clap::builder::command::Command::_do_parse (1 samples, 0.03%)clap::parser::parser::Parser::get_matches_with (1 samples, 0.03%)clap::parser::parser::Parser::parse_subcommand (1 samples, 0.03%)clap::parser::parser::Parser::get_matches_with (1 samples, 0.03%)clap::parser::validator::Validator::validate (1 samples, 0.03%)clap::parser::validator::Validator::validate_required (1 samples, 0.03%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::find (1 samples, 0.03%)core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1 samples, 0.03%)clap::parser::validator::Validator::validate_required::{{closure}} (1 samples, 0.03%)clap::parser::arg_matcher::ArgMatcher::check_explicit (1 samples, 0.03%)clap::parser::arg_matcher::ArgMatcher::get (1 samples, 0.03%)clap::util::flat_map::FlatMap<K,V>::get (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)clap::derive::Parser::parse (1 samples, 0.03%)clap::builder::command::Command::get_matches (1 samples, 0.03%)clap::builder::command::Command::get_matches_from (1 samples, 0.03%)clap::builder::command::Command::try_get_matches_from_mut (1 samples, 0.03%)clap::builder::command::Command::_do_parse (1 samples, 0.03%)clap::builder::command::Command::_build_self (1 samples, 0.03%)clap::builder::debug_asserts::assert_app (1 samples, 0.03%)core::str::<impl str>::starts_with (1 samples, 0.03%)<char as core::str::pattern::Pattern>::is_prefix_of (1 samples, 0.03%)tftp::server::connection::ConnectionBuilder::with_request (1 samples, 0.03%)tftp::server::extensions::create_options (1 samples, 0.03%)tftp::key_management::create_finalized_keys (1 samples, 0.03%)tftp::key_management::create_initial_keys (1 samples, 0.03%)<x25519_dalek::x25519::PublicKey as core::convert::From<&x25519_dalek::x25519::EphemeralSecret>>::from (1 samples, 0.03%)<&curve25519_dalek::edwards::EdwardsBasepointTable as core::ops::arith::Mul<&curve25519_dalek::scalar::Scalar>>::mul (1 samples, 0.03%)curve25519_dalek::edwards::EdwardsBasepointTable::basepoint_mul (1 samples, 0.03%)curve25519_dalek::edwards::EdwardsPoint::mul_by_pow_2 (1 samples, 0.03%)curve25519_dalek::backend::serial::curve_models::ProjectivePoint::double (1 samples, 0.03%)curve25519_dalek::backend::serial::u64::field::FieldElement51::square (1 samples, 0.03%)curve25519_dalek::backend::serial::u64::field::FieldElement51::pow2k (1 samples, 0.03%)<T as core::convert::Into<U>>::into (1 samples, 0.03%)<core::option::Option<T> as core::convert::From<T>>::from (1 samples, 0.03%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 0.06%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (5 samples, 0.15%)tftp::packet::try_from (4 samples, 0.12%)core::slice::<impl [T]>::get (2 samples, 0.06%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.03%)core::mem::size_of_val (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)core::num::<impl u16>::from_be_bytes (1 samples, 0.03%)core::num::<impl u16>::from_ne_bytes (1 samples, 0.03%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (10 samples, 0.31%)tftp::packet::PacketType::from_bytes (4 samples, 0.12%)tftp::packet::try_from (4 samples, 0.12%)core::option::Option<T>::ok_or (1 samples, 0.03%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (3 samples, 0.09%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (3 samples, 0.09%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.06%)alloc::raw_vec::RawVec<T,A>::current_memory (1 samples, 0.03%)core::result::Result<T,E>::map (2 samples, 0.06%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from::{{closure}} (2 samples, 0.06%)tftp::socket::std_to_socket_addr (2 samples, 0.06%)std::net::socket_addr::SocketAddrV4::ip (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.06%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (2 samples, 0.06%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::ErrorData<alloc::boxed::Box<std::io::error::Custom>>> (1 samples, 0.03%)std::io::error::repr_bitpacked::Repr::data (1 samples, 0.03%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.03%)core::result::Result<T,E>::map_err (8 samples, 0.25%)core::ops::function::FnOnce::call_once (5 samples, 0.15%)tftp::io::from_io_err (4 samples, 0.12%)std::io::error::Error::kind (2 samples, 0.06%)std::sys::unix::decode_error_kind (1 samples, 0.03%)polling::Event::readable (1 samples, 0.03%)<&T as polling::Source>::raw (1 samples, 0.03%)std::os::fd::net::<impl std::os::fd::raw::AsRawFd for std::net::udp::UdpSocket>::as_raw_fd (1 samples, 0.03%)<std::sys::unix::fs::File as std::sys_common::AsInner<std::sys::unix::fd::FileDesc>>::as_inner (1 samples, 0.03%)log::max_level (1 samples, 0.03%)core::sync::atomic::AtomicUsize::load (1 samples, 0.03%)core::sync::atomic::atomic_load (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)core::option::Option<T>::as_mut (1 samples, 0.03%)polling::Poller::modify (7 samples, 0.22%)polling::epoll::Poller::modify (6 samples, 0.19%)polling::epoll::Poller::ctl (3 samples, 0.09%)core::option::Option<T>::map (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.03%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.15%)core::iter::traits::iterator::Iterator::find (5 samples, 0.15%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (4 samples, 0.12%)core::iter::traits::iterator::Iterator::try_fold (3 samples, 0.09%)core::iter::adapters::map::map_try_fold::{{closure}} (1 samples, 0.03%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::size_hint (4 samples, 0.12%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::size_hint (3 samples, 0.09%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::size_hint (3 samples, 0.09%)core::ptr::const_ptr::<impl *const T>::sub_ptr (1 samples, 0.03%)__rdl_alloc (1 samples, 0.03%)alloc::alloc::alloc (2 samples, 0.06%)malloc (1 samples, 0.03%)core::option::Option<T>::ok_or (1 samples, 0.03%)alloc::raw_vec::finish_grow (5 samples, 0.15%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (5 samples, 0.15%)alloc::alloc::Global::alloc_impl (5 samples, 0.15%)core::ptr::non_null::NonNull<[T]>::slice_from_raw_parts (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)alloc::vec::Vec<T,A>::reserve (9 samples, 0.28%)alloc::raw_vec::RawVec<T,A>::reserve (8 samples, 0.25%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (7 samples, 0.22%)alloc::raw_vec::RawVec<T,A>::grow_amortized (6 samples, 0.19%)core::cmp::max (1 samples, 0.03%)core::cmp::Ord::max (1 samples, 0.03%)core::cmp::max_by (1 samples, 0.03%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (23 samples, 0.71%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (21 samples, 0.65%)alloc::vec::Vec<T,A>::extend_desugared (21 samples, 0.65%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::iter::traits::iterator::Iterator::filter (2 samples, 0.06%)polling::epoll::Events::iter (1 samples, 0.03%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.06%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 0.06%)[libc.so.6] (1 samples, 0.03%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.03%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.03%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.03%)std::io::error::repr_bitpacked::decode_repr (1 samples, 0.03%)core::time::Duration::from_secs (1 samples, 0.03%)core::time::Duration::new (1 samples, 0.03%)core::num::<impl u64>::checked_add (1 samples, 0.03%)epoll_wait (27 samples, 0.84%)polling::epoll::Poller::modify (1 samples, 0.03%)polling::epoll::Poller::ctl (1 samples, 0.03%)core::option::Option<T>::unwrap_or (1 samples, 0.03%)polling::epoll::Poller::wait (39 samples, 1.21%)read (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)polling::Poller::wait (67 samples, 2.07%)p..std::sync::mutex::Mutex<T>::try_lock (2 samples, 0.06%)std::sys::unix::locks::futex_mutex::Mutex::try_lock (1 samples, 0.03%)core::sync::atomic::AtomicU32::compare_exchange (1 samples, 0.03%)core::sync::atomic::atomic_compare_exchange (1 samples, 0.03%)recvfrom (1 samples, 0.03%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (92 samples, 2.85%)<t..std::net::udp::UdpSocket::recv_from (3 samples, 0.09%)std::sys_common::net::UdpSocket::recv_from (3 samples, 0.09%)std::sys::unix::net::Socket::recv_from (3 samples, 0.09%)std::sys::unix::net::Socket::recv_from_with_flags (2 samples, 0.06%)std::sys::unix::cvt (1 samples, 0.03%)std::io::error::Error::last_os_error (1 samples, 0.03%)std::io::error::Error::from_raw_os_error (1 samples, 0.03%)std::io::error::repr_bitpacked::Repr::new_os (1 samples, 0.03%)core::cmp::PartialOrd::gt (1 samples, 0.03%)core::ptr::drop_in_place<core::result::Result<(),tftp::packet::ErrorPacket>> (1 samples, 0.03%)core::slice::<impl [T]>::len (1 samples, 0.03%)core::time::Duration::from_secs (2 samples, 0.06%)core::time::Duration::new (2 samples, 0.06%)core::num::<impl u64>::checked_add (1 samples, 0.03%)core::ops::function::FnOnce::call_once (5 samples, 0.15%)tftp::instant_callback::{{closure}} (5 samples, 0.15%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (4 samples, 0.12%)clock_gettime (4 samples, 0.12%)__vdso_clock_gettime (3 samples, 0.09%)tftp::instant_callback (6 samples, 0.19%)tftp::std_compat::time::Instant::from_time (6 samples, 0.19%)core::time::Duration::from_micros (1 samples, 0.03%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (1 samples, 0.03%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::find (1 samples, 0.03%)tftp::map::Map<K,V,_>::entry::{{closure}} (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialEq<&B> for &A>::eq (1 samples, 0.03%)<tftp::std_compat::net::SocketAddr as core::cmp::PartialEq>::eq (1 samples, 0.03%)<tftp::std_compat::net::IpVersion as core::cmp::PartialEq>::eq (1 samples, 0.03%)tftp::map::Map<K,V,_>::entry (4 samples, 0.12%)core::slice::<impl [T]>::iter (2 samples, 0.06%)core::slice::iter::Iter<T>::new (1 samples, 0.03%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)arrayvec::arrayvec::ArrayVec<T,_>::as_mut_slice (1 samples, 0.03%)arrayvec::arrayvec_impl::ArrayVecImpl::as_mut_slice (1 samples, 0.03%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::find (1 samples, 0.03%)tftp::map::OccupiedEntry<K,V,_>::get_mut (3 samples, 0.09%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)tftp::packet::PacketType::from_bytes (1 samples, 0.03%)tftp::packet::try_from (1 samples, 0.03%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (5 samples, 0.15%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (4 samples, 0.12%)core::result::Result<T,E>::map (2 samples, 0.06%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (1 samples, 0.03%)chacha20::avx2_cpuid::init (3 samples, 0.09%)chacha20::avx2_cpuid::init_get (2 samples, 0.06%)core::sync::atomic::AtomicU8::load (2 samples, 0.06%)core::sync::atomic::atomic_load (2 samples, 0.06%)chacha20::sse2_cpuid::init (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (3 samples, 0.09%)core::iter::adapters::zip::Zip<A,B>::new (2 samples, 0.06%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.03%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.03%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.03%)core::result::Result<T,E>::unwrap (1 samples, 0.03%)core::slice::<impl [T]>::chunks_exact (1 samples, 0.03%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (16 samples, 0.50%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (2 samples, 0.06%)[libc.so.6] (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (7 samples, 0.22%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (6 samples, 0.19%)core::result::Result<T,E>::map (4 samples, 0.12%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (2 samples, 0.06%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (4 samples, 0.12%)core::slice::raw::from_raw_parts (2 samples, 0.06%)core::ptr::slice_from_raw_parts (1 samples, 0.03%)core::ptr::metadata::from_raw_parts (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (7 samples, 0.22%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (6 samples, 0.19%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (2 samples, 0.06%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::num::<impl u32>::rotate_left (5 samples, 0.15%)chacha20::xchacha::quarter_round (42 samples, 1.30%)core::num::<impl u32>::wrapping_add (3 samples, 0.09%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (2 samples, 0.06%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.06%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.06%)core::array::<impl core::ops::index::IndexMut<I> for [T: N]>::index_mut (2 samples, 0.06%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (5 samples, 0.15%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.09%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.06%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)core::cmp::min (1 samples, 0.03%)core::cmp::Ord::min (1 samples, 0.03%)<core::slice::iter::ChunksExactMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (5 samples, 0.15%)core::iter::adapters::zip::Zip<A,B>::new (3 samples, 0.09%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (3 samples, 0.09%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (2 samples, 0.06%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.03%)core::num::<impl u32>::to_le_bytes (1 samples, 0.03%)core::num::<impl u32>::to_ne_bytes (1 samples, 0.03%)core::result::Result<T,E>::unwrap (3 samples, 0.09%)core::slice::<impl [T]>::copy_from_slice (1 samples, 0.03%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::iter::IterMut<T>::new (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.03%)core::iter::adapters::enumerate::Enumerate<I>::new (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (9 samples, 0.28%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (8 samples, 0.25%)core::iter::traits::iterator::Iterator::fold (8 samples, 0.25%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.09%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)chacha20::xchacha::hchacha (98 samples, 3.03%)cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (13 samples, 0.40%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (13 samples, 0.40%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.06%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (5 samples, 0.15%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (5 samples, 0.15%)core::iter::traits::iterator::Iterator::fold (5 samples, 0.15%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (2 samples, 0.06%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (126 samples, 3.90%)<cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (10 samples, 0.31%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (10 samples, 0.31%)generic_array::ArrayBuilder<T,N>::new (1 samples, 0.03%)core::ptr::write (2 samples, 0.06%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (15 samples, 0.46%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (11 samples, 0.34%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (10 samples, 0.31%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (2 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (25 samples, 0.77%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (25 samples, 0.77%)core::iter::traits::iterator::Iterator::fold (25 samples, 0.77%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (8 samples, 0.25%)core::slice::iter::IterMut<T>::post_inc_start (4 samples, 0.12%)core::ptr::non_null::NonNull<T>::new_unchecked (2 samples, 0.06%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (3 samples, 0.09%)core::ptr::read (1 samples, 0.03%)memcpy (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (159 samples, 4.92%)<ciphe..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (32 samples, 0.99%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (32 samples, 0.99%)generic_array::ArrayBuilder<T,N>::iter_position (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.03%)core::convert::num::ptr_try_from_impls::<impl core::convert::TryFrom<usize> for u64>::try_from (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)core::result::Result<T,E>::map_err (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (3 samples, 0.09%)core::iter::traits::iterator::Iterator::fold (3 samples, 0.09%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (3 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.06%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (12 samples, 0.37%)universal_hash::UniversalHash::update (3 samples, 0.09%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (3 samples, 0.09%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (3 samples, 0.09%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (3 samples, 0.09%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (3 samples, 0.09%)poly1305::backend::soft::State::compute_block (3 samples, 0.09%)<T as core::convert::TryInto<U>>::try_into (3 samples, 0.09%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (2 samples, 0.06%)core::core_arch::x86::sse2::_mm_add_epi32 (112 samples, 3.47%)cor..core::core_arch::x86::m128iExt::as_i32x4 (18 samples, 0.56%)core::core_arch::x86::sse2::_mm_slli_epi32 (76 samples, 2.35%)c..core::core_arch::x86::m128iExt::as_i32x4 (18 samples, 0.56%)core::core_arch::x86::sse2::_mm_srli_epi32 (20 samples, 0.62%)core::core_arch::x86::m128iExt::as_i32x4 (9 samples, 0.28%)chacha20::backends::sse2::add_xor_rot (487 samples, 15.08%)chacha20::backends::sse..core::core_arch::x86::sse2::_mm_xor_si128 (68 samples, 2.11%)c..chacha20::backends::sse2::cols_to_rows (33 samples, 1.02%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (20 samples, 0.62%)core::core_arch::x86::m128iExt::as_i32x4 (8 samples, 0.25%)chacha20::backends::sse2::double_quarter_round (547 samples, 16.94%)chacha20::backends::sse2::..chacha20::backends::sse2::rows_to_cols (22 samples, 0.68%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (15 samples, 0.46%)core::core_arch::x86::m128iExt::as_i32x4 (4 samples, 0.12%)<usize as core::iter::range::Step>::forward_unchecked (8 samples, 0.25%)core::num::<impl usize>::unchecked_add (3 samples, 0.09%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (6 samples, 0.19%)chacha20::backends::sse2::rounds (613 samples, 18.98%)chacha20::backends::sse2::roun..core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (46 samples, 1.42%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (43 samples, 1.33%)core::mem::replace (13 samples, 0.40%)core::ptr::read (10 samples, 0.31%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.09%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (3 samples, 0.09%)core::core_arch::x86::sse2::_mm_add_epi32 (2 samples, 0.06%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_set_epi32 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_storeu_si128 (2 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (630 samples, 19.51%)<chacha20::backends::sse2::Back..core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<inout::inout_buf::InOutBufIter<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.09%)inout::inout_buf::InOutBuf<T>::len (1 samples, 0.03%)core::iter::traits::iterator::Iterator::enumerate (1 samples, 0.03%)core::ptr::write (19 samples, 0.59%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (220 samples, 6.81%)<core::it..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (168 samples, 5.20%)core::..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (127 samples, 3.93%)<gen..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (34 samples, 1.05%)<u8 as core::default::Default>::default (5 samples, 0.15%)core::ptr::mut_ptr::<impl *mut T>::is_null (45 samples, 1.39%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (22 samples, 0.68%)core::ptr::mut_ptr::<impl *mut T>::addr (11 samples, 0.34%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (27 samples, 0.84%)core::ptr::mut_ptr::<impl *mut T>::offset (27 samples, 0.84%)core::ptr::non_null::NonNull<T>::as_ptr (4 samples, 0.12%)core::iter::traits::iterator::Iterator::for_each (465 samples, 14.40%)core::iter::traits::it..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (461 samples, 14.28%)<core::iter::adapters:..core::iter::traits::iterator::Iterator::fold (461 samples, 14.28%)core::iter::traits::it..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (152 samples, 4.71%)<core..core::slice::iter::IterMut<T>::post_inc_start (72 samples, 2.23%)c..core::ptr::non_null::NonNull<T>::new_unchecked (5 samples, 0.15%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (3 samples, 0.09%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (2 samples, 0.06%)memcpy (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (2 samples, 0.06%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::into_inner (10 samples, 0.31%)core::ptr::read (5 samples, 0.15%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (4 samples, 0.12%)memcpy (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::iter_position (4 samples, 0.12%)core::slice::<impl [T]>::iter_mut (2 samples, 0.06%)core::slice::iter::IterMut<T>::new (2 samples, 0.06%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (484 samples, 14.99%)generic_array::impls::<..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (483 samples, 14.96%)<generic_array::Generic..generic_array::ArrayBuilder<T,N>::new (2 samples, 0.06%)[libc.so.6] (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)core::ptr::const_ptr::<impl *const T>::cast (2 samples, 0.06%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (129 samples, 4.00%)<gen..core::slice::raw::from_raw_parts (112 samples, 3.47%)cor..core::ptr::slice_from_raw_parts (83 samples, 2.57%)co..core::ptr::metadata::from_raw_parts (64 samples, 1.98%)c..<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (51 samples, 1.58%)core::slice::raw::from_raw_parts_mut (37 samples, 1.15%)core::ptr::slice_from_raw_parts_mut (25 samples, 0.77%)core::ptr::metadata::from_raw_parts_mut (18 samples, 0.56%)<usize as core::iter::range::Step>::forward_unchecked (20 samples, 0.62%)core::num::<impl usize>::unchecked_add (2 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (18 samples, 0.56%)core::ptr::read (48 samples, 1.49%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (11 samples, 0.34%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (10 samples, 0.31%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (189 samples, 5.85%)core::i..<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (170 samples, 5.26%)<core:..core::mem::replace (79 samples, 2.45%)co..core::ptr::write (9 samples, 0.28%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.03%)memcpy (1 samples, 0.03%)core::ptr::read (3 samples, 0.09%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.06%)memcpy (1 samples, 0.03%)core::ptr::write (26 samples, 0.81%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (220 samples, 6.81%)<core::it..core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (161 samples, 4.99%)core::..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (125 samples, 3.87%)<gen..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default::{{closure}} (26 samples, 0.81%)<u8 as core::default::Default>::default (3 samples, 0.09%)core::ptr::mut_ptr::<impl *mut T>::is_null (42 samples, 1.30%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (21 samples, 0.65%)core::ptr::mut_ptr::<impl *mut T>::addr (13 samples, 0.40%)core::ptr::mut_ptr::<impl *mut T>::add (23 samples, 0.71%)core::ptr::mut_ptr::<impl *mut T>::offset (19 samples, 0.59%)core::ptr::non_null::NonNull<T>::as_ptr (3 samples, 0.09%)core::iter::traits::iterator::Iterator::for_each (461 samples, 14.28%)core::iter::traits::it..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (460 samples, 14.25%)<core::iter::adapters:..core::iter::traits::iterator::Iterator::fold (460 samples, 14.25%)core::iter::traits::it..<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (160 samples, 4.96%)<core:..core::slice::iter::IterMut<T>::post_inc_start (77 samples, 2.38%)co..core::ptr::non_null::NonNull<T>::new_unchecked (6 samples, 0.19%)[libc.so.6] (1 samples, 0.03%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (2 samples, 0.06%)memcpy (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)[libc.so.6] (2 samples, 0.06%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (4 samples, 0.12%)memcpy (2 samples, 0.06%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (6 samples, 0.19%)memcpy (1 samples, 0.03%)core::ptr::read (9 samples, 0.28%)memcpy (2 samples, 0.06%)generic_array::ArrayBuilder<T,N>::into_inner (17 samples, 0.53%)memcpy (1 samples, 0.03%)<generic_array::GenericArray<T,N> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.03%)core::slice::raw::from_raw_parts_mut (1 samples, 0.03%)core::ptr::slice_from_raw_parts_mut (1 samples, 0.03%)core::ptr::metadata::from_raw_parts_mut (1 samples, 0.03%)generic_array::ArrayBuilder<T,N>::iter_position (7 samples, 0.22%)core::slice::<impl [T]>::iter_mut (4 samples, 0.12%)core::slice::iter::IterMut<T>::new (3 samples, 0.09%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.03%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (2,170 samples, 67.20%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::callinout::inout::InOut<generic_array::GenericArray<u8,N>>::xor_in2out (1,052 samples, 32.58%)inout::inout::InOut<generic_array::GenericArray<u8,N>..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (491 samples, 15.21%)generic_array::impls::<..<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (491 samples, 15.21%)<generic_array::Generic..generic_array::ArrayBuilder<T,N>::new (2 samples, 0.06%)[libc.so.6] (2 samples, 0.06%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (2,174 samples, 67.33%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2,174 samples, 67.33%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (2,174 samples, 67.33%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backendchacha20::backends::sse2::inner (2,173 samples, 67.30%)chacha20::backends::sse2::innercore::core_arch::x86::sse2::_mm_loadu_si128 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (6 samples, 0.19%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_slli_epi32 (5 samples, 0.15%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.06%)chacha20::backends::sse2::add_xor_rot (22 samples, 0.68%)core::core_arch::x86::sse2::_mm_srli_epi32 (1 samples, 0.03%)chacha20::backends::sse2::double_quarter_round (23 samples, 0.71%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.03%)chacha20::backends::sse2::rounds (24 samples, 0.74%)core::core_arch::x86::sse2::_mm_add_epi32 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_set_epi32 (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (30 samples, 0.93%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (30 samples, 0.93%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (30 samples, 0.93%)chacha20::backends::sse2::inner (29 samples, 0.90%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (28 samples, 0.87%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (28 samples, 0.87%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (2 samples, 0.06%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (2,218 samples, 68.69%)cipher::stream::StreamCipher::apply_keystreamcipher::stream::StreamCipher::try_apply_keystream (2,218 samples, 68.69%)cipher::stream::StreamCipher::try_apply_keystream<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (2,218 samples, 68.69%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inoutinout::inout_buf::InOutBuf<u8>::xor_in2out (11 samples, 0.34%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (7 samples, 0.22%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.15%)core::mem::replace (3 samples, 0.09%)core::ptr::read (3 samples, 0.09%)<Z as zeroize::Zeroize>::zeroize (2 samples, 0.06%)zeroize::atomic_fence (1 samples, 0.03%)core::sync::atomic::compiler_fence (1 samples, 0.03%)<usize as core::iter::range::Step>::forward_unchecked (3 samples, 0.09%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (1 samples, 0.03%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (8 samples, 0.25%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (8 samples, 0.25%)core::mem::replace (3 samples, 0.09%)core::ptr::read (2 samples, 0.06%)core::ptr::mut_ptr::<impl *mut T>::add (2 samples, 0.06%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (14 samples, 0.43%)<[Z] as zeroize::Zeroize>::zeroize (12 samples, 0.37%)zeroize::volatile_set (12 samples, 0.37%)core::ptr::write_volatile (1 samples, 0.03%)<&mut I as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)<core::slice::iter::IterMut<Z> as zeroize::Zeroize>::zeroize (6 samples, 0.19%)<Z as zeroize::Zeroize>::zeroize (2 samples, 0.06%)zeroize::atomic_fence (1 samples, 0.03%)core::sync::atomic::compiler_fence (1 samples, 0.03%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (22 samples, 0.68%)core::ptr::drop_in_place<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (8 samples, 0.25%)core::ptr::drop_in_place<chacha20::ChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>> (8 samples, 0.25%)<chacha20::ChaChaCore<R> as core::ops::drop::Drop>::drop (7 samples, 0.22%)<[Z: N] as zeroize::Zeroize>::zeroize (7 samples, 0.22%)core::slice::<impl [T]>::iter_mut (1 samples, 0.03%)core::slice::<impl [T]>::copy_from_slice (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (2 samples, 0.06%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (5 samples, 0.15%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (5 samples, 0.15%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (4 samples, 0.12%)core::ptr::write (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (6 samples, 0.19%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (6 samples, 0.19%)core::iter::traits::iterator::Iterator::fold (6 samples, 0.19%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)core::ptr::non_null::NonNull<T>::as_ptr (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (8 samples, 0.25%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (8 samples, 0.25%)generic_array::ArrayBuilder<T,N>::iter_position (2 samples, 0.06%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (5 samples, 0.15%)core::slice::iter::Iter<T>::post_inc_start (5 samples, 0.15%)core::ptr::non_null::NonNull<T>::new_unchecked (1 samples, 0.03%)core::array::<impl core::convert::TryFrom<&[T]> for &[T: N]>::try_from (23 samples, 0.71%)<T as core::convert::TryInto<U>>::try_into (133 samples, 4.12%)<T a..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (110 samples, 3.41%)cor..core::result::Result<T,E>::map (66 samples, 2.04%)c..core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (12 samples, 0.37%)core::ptr::const_ptr::<impl *const T>::cast (2 samples, 0.06%)<generic_array::GenericArray<T,N> as core::ops::deref::Deref>::deref (11 samples, 0.34%)core::slice::raw::from_raw_parts (8 samples, 0.25%)core::ptr::slice_from_raw_parts (5 samples, 0.15%)core::ptr::metadata::from_raw_parts (3 samples, 0.09%)core::convert::num::<impl core::convert::From<u32> for u64>::from (4 samples, 0.12%)core::num::<impl u32>::from_le_bytes (40 samples, 1.24%)core::num::<impl u32>::from_ne_bytes (18 samples, 0.56%)core::result::Result<T,E>::unwrap (49 samples, 1.52%)core::ptr::const_ptr::<impl *const T>::add (8 samples, 0.25%)core::ptr::const_ptr::<impl *const T>::offset (7 samples, 0.22%)core::ptr::const_ptr::<impl *const [T]>::as_ptr (1 samples, 0.03%)core::ptr::const_ptr::<impl *const T>::cast (4 samples, 0.12%)<poly1305::backend::soft::State as universal_hash::UhfBackend>::proc_block (437 samples, 13.53%)<poly1305::backend::..poly1305::backend::soft::State::compute_block (437 samples, 13.53%)poly1305::backend::s..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (74 samples, 2.29%)c..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (66 samples, 2.04%)<..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (54 samples, 1.67%)core::ptr::slice_from_raw_parts (23 samples, 0.71%)core::ptr::metadata::from_raw_parts (18 samples, 0.56%)universal_hash::UniversalHash::update (448 samples, 13.87%)universal_hash::Unive..<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (447 samples, 13.84%)<poly1305::Poly1305 a..<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (447 samples, 13.84%)<poly1305::backend::a..<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (445 samples, 13.78%)<universal_hash::Univ..core::slice::iter::<impl core::iter::traits::collect::IntoIterator for &[T]>::into_iter (1 samples, 0.03%)core::slice::<impl [T]>::iter (1 samples, 0.03%)core::slice::iter::Iter<T>::new (1 samples, 0.03%)universal_hash::UniversalHash::update_padded (461 samples, 14.28%)universal_hash::Univer..universal_hash::to_blocks (2 samples, 0.06%)core::slice::<impl [T]>::split_at (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.09%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next (2 samples, 0.06%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::__iterator_get_unchecked (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)<u8 as subtle::ConstantTimeEq>::ct_eq (3 samples, 0.09%)<T as core::convert::Into<U>>::into (2 samples, 0.06%)<subtle::Choice as core::convert::From<u8>>::from (2 samples, 0.06%)subtle::black_box (2 samples, 0.06%)core::iter::traits::iterator::Iterator::zip (3 samples, 0.09%)core::iter::adapters::zip::Zip<A,B>::new (2 samples, 0.06%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (2 samples, 0.06%)core::cmp::min (2 samples, 0.06%)core::cmp::Ord::min (2 samples, 0.06%)core::cmp::min_by (2 samples, 0.06%)core::ops::function::FnOnce::call_once (1 samples, 0.03%)<[T] as subtle::ConstantTimeEq>::ct_eq (11 samples, 0.34%)core::slice::<impl [T]>::iter (1 samples, 0.03%)core::slice::iter::Iter<T>::new (1 samples, 0.03%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.03%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (4 samples, 0.12%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (4 samples, 0.12%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each (7 samples, 0.22%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (7 samples, 0.22%)core::iter::traits::iterator::Iterator::fold (7 samples, 0.22%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (2 samples, 0.06%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detached (2,734 samples, 84.67%)chacha20poly1305::cipher::Cipher<C>::decrypt_in_place_detacheduniversal_hash::UniversalHash::verify (21 samples, 0.65%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (10 samples, 0.31%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (10 samples, 0.31%)poly1305::backend::soft::State::finalize_mut (10 samples, 0.31%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (8 samples, 0.25%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (8 samples, 0.25%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (8 samples, 0.25%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (6 samples, 0.19%)core::mem::replace (1 samples, 0.03%)core::ptr::read (1 samples, 0.03%)<[Z] as zeroize::Zeroize>::zeroize (10 samples, 0.31%)zeroize::volatile_set (10 samples, 0.31%)core::ptr::write_volatile (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)core::mem::manually_drop::ManuallyDrop<T>::new (2 samples, 0.06%)[libc.so.6] (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (4 samples, 0.12%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (3 samples, 0.09%)core::result::Result<T,E>::map (2 samples, 0.06%)<poly1305::backend::soft::State as core::default::Default>::default (2 samples, 0.06%)core::array::<impl core::default::Default for [T: _]>::default (1 samples, 0.03%)core::result::Result<T,E>::unwrap (2 samples, 0.06%)<poly1305::Poly1305 as crypto_common::KeyInit>::new (14 samples, 0.43%)poly1305::backend::autodetect::State::new (14 samples, 0.43%)poly1305::backend::soft::State::new (11 samples, 0.34%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (2 samples, 0.06%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (2 samples, 0.06%)core::ptr::slice_from_raw_parts (2 samples, 0.06%)core::ptr::metadata::from_raw_parts (2 samples, 0.06%)[libc.so.6] (1 samples, 0.03%)<T as core::convert::Into<U>>::into (1 samples, 0.03%)<cipher::stream_core::ApplyBlocksCtx<BS> as cipher::stream_core::StreamClosure>::call (1 samples, 0.03%)<inout::inout_buf::InOutBufIter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::apply_keystream_blocks_inout (3 samples, 0.09%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.09%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (3 samples, 0.09%)chacha20::backends::sse2::inner (3 samples, 0.09%)core::core_arch::x86::sse2::_mm_loadu_si128 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_undefined_si128 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_add_epi32 (7 samples, 0.22%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_slli_epi32 (4 samples, 0.12%)core::core_arch::x86::m128iExt::as_i32x4 (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_srli_epi32 (5 samples, 0.15%)core::core_arch::x86::m128iExt::as_i32x4 (2 samples, 0.06%)chacha20::backends::sse2::add_xor_rot (40 samples, 1.24%)core::core_arch::x86::sse2::_mm_xor_si128 (6 samples, 0.19%)chacha20::backends::sse2::cols_to_rows (3 samples, 0.09%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (2 samples, 0.06%)chacha20::backends::sse2::double_quarter_round (44 samples, 1.36%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.03%)chacha20::backends::sse2::rounds (48 samples, 1.49%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)cipher::stream_core::StreamCipherCore::write_keystream_block (54 samples, 1.67%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (54 samples, 1.67%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (54 samples, 1.67%)chacha20::backends::sse2::inner (54 samples, 1.67%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (54 samples, 1.67%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (51 samples, 1.58%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (2 samples, 0.06%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (2 samples, 0.06%)core::mem::replace (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::check_remaining (1 samples, 0.03%)cipher::stream_wrapper::StreamCipherCoreWrapper<T>::set_pos_unchecked (1 samples, 0.03%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.03%)core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt (2 samples, 0.06%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (6 samples, 0.19%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (5 samples, 0.15%)core::mem::replace (2 samples, 0.06%)core::ptr::read (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (72 samples, 2.23%)c..cipher::stream::StreamCipher::try_apply_keystream (72 samples, 2.23%)c..<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (71 samples, 2.20%)<..inout::inout_buf::InOutBuf<u8>::xor_in2out (10 samples, 0.31%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.03%)generic_array::GenericArray<T,N>::from_slice (3 samples, 0.09%)<T as core::convert::Into<U>>::into (3 samples, 0.09%)<&generic_array::GenericArray<T,N> as core::convert::From<&[T]>>::from (2 samples, 0.06%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (5 samples, 0.15%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (3 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (2 samples, 0.06%)core::ptr::write (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.03%)core::ptr::mut_ptr::<impl *mut T>::addr (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (10 samples, 0.31%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (10 samples, 0.31%)core::iter::traits::iterator::Iterator::fold (10 samples, 0.31%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.09%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detached (3,005 samples, 93.06%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::decrypt_in_place_detachedchacha20poly1305::cipher::Cipher<C>::new (111 samples, 3.44%)cha..generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (11 samples, 0.34%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (11 samples, 0.34%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)<heapless::vec::Vec<u8,_> as aead::Buffer>::truncate (2 samples, 0.06%)heapless::vec::Vec<T,_>::truncate (1 samples, 0.03%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.03%)<typenum::uint::UInt<U,B> as typenum::marker_traits::Unsigned>::to_usize (1 samples, 0.03%)aead::Buffer::len (1 samples, 0.03%)<heapless::vec::Vec<T,_> as core::convert::AsRef<[T]>>::as_ref (1 samples, 0.03%)<heapless::vec::Vec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.03%)heapless::vec::Vec<T,_>::as_slice (1 samples, 0.03%)core::slice::raw::from_raw_parts (1 samples, 0.03%)tftp::encryption::Encryptor::decrypt (3,013 samples, 93.31%)tftp::encryption::Encryptor::decryptaead::AeadInPlace::decrypt_in_place (3,012 samples, 93.28%)aead::AeadInPlace::decrypt_in_placegeneric_array::GenericArray<T,N>::from_slice (1 samples, 0.03%)<T as core::convert::Into<U>>::into (1 samples, 0.03%)<&generic_array::GenericArray<T,N> as core::convert::From<&[T]>>::from (1 samples, 0.03%)<T as core::convert::TryInto<U>>::try_into (4 samples, 0.12%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (4 samples, 0.12%)core::result::Result<T,E>::map (4 samples, 0.12%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (3 samples, 0.09%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)tftp::server::connection::Connection<R,W,S>::receive_packet (3,020 samples, 93.53%)tftp::server::connection::Connection<R,W,S>::receive_packettftp::packet::PacketType::from_bytes (6 samples, 0.19%)tftp::packet::try_from (6 samples, 0.19%)core::slice::<impl [T]>::get (1 samples, 0.03%)tftp::server::connection::ConnectionBuilder::with_request (1 samples, 0.03%)tftp::server::extensions::create_options (1 samples, 0.03%)tftp::key_management::create_finalized_keys (1 samples, 0.03%)tftp::encryption::InitialKeys::finalize (1 samples, 0.03%)x25519_dalek::x25519::EphemeralSecret::diffie_hellman (1 samples, 0.03%)curve25519_dalek::montgomery::<impl core::ops::arith::Mul<curve25519_dalek::montgomery::MontgomeryPoint> for curve25519_dalek::scalar::Scalar>::mul (1 samples, 0.03%)curve25519_dalek::montgomery::<impl core::ops::arith::Mul<&curve25519_dalek::montgomery::MontgomeryPoint> for &curve25519_dalek::scalar::Scalar>::mul (1 samples, 0.03%)<&curve25519_dalek::montgomery::MontgomeryPoint as core::ops::arith::Mul<&curve25519_dalek::scalar::Scalar>>::mul (1 samples, 0.03%)curve25519_dalek::montgomery::differential_add_and_double (1 samples, 0.03%)<&curve25519_dalek::backend::serial::u64::field::FieldElement51 as core::ops::arith::Mul<&curve25519_dalek::backend::serial::u64::field::FieldElement51>>::mul (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)tftp::server::server::send_data_blocks (8 samples, 0.25%)tftp::map::Map<K,V,_>::retain (7 samples, 0.22%)arrayvec::arrayvec::ArrayVec<T,_>::retain (6 samples, 0.19%)arrayvec::arrayvec::ArrayVec<T,_>::retain::process_one (6 samples, 0.19%)tftp::map::Map<K,V,_>::retain::{{closure}} (4 samples, 0.12%)tftp::server::server::send_data_blocks::{{closure}} (4 samples, 0.12%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (3 samples, 0.09%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (3 samples, 0.09%)<i32 as core::iter::range::Step>::forward_unchecked (1 samples, 0.03%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.03%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.03%)<tftp::io::StdCompatFile as tftp::std_compat::io::Write>::write (1 samples, 0.03%)std::os::unix::net::datagram::UnixDatagram::send (1 samples, 0.03%)<tftp::storage::BlockMapper as core::clone::Clone>::clone (1 samples, 0.03%)tftp::map::Map<K,V,_>::get (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::find (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (1 samples, 0.03%)tftp::map::Map<K,V,_>::remove (3 samples, 0.09%)core::option::Option<T>::and_then (1 samples, 0.03%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (11 samples, 0.34%)tftp::storage::BlockMapper::index (1 samples, 0.03%)log::max_level (1 samples, 0.03%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (2 samples, 0.06%)std::net::udp::UdpSocket::send_to (2 samples, 0.06%)std::sys_common::net::UdpSocket::send_to (1 samples, 0.03%)std::sys::unix::cvt (1 samples, 0.03%)<isize as std::sys::unix::IsMinusOne>::is_minus_one (1 samples, 0.03%)<chacha20::ChaChaCore<R> as crypto_common::KeyIvInit>::new (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::new (1 samples, 0.03%)core::iter::adapters::zip::TrustedRandomAccessNoCoerce::size (1 samples, 0.03%)<core::slice::iter::ChunksExact<T> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.03%)<core::iter::adapters::zip::Zip<A,B> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)chacha20::xchacha::quarter_round (3 samples, 0.09%)core::num::<impl u32>::wrapping_add (1 samples, 0.03%)core::iter::traits::iterator::Iterator::zip (1 samples, 0.03%)core::iter::adapters::zip::Zip<A,B>::new (1 samples, 0.03%)[libc.so.6] (1 samples, 0.03%)<chacha20::xchacha::XChaChaCore<R> as crypto_common::KeyIvInit>::new (7 samples, 0.22%)chacha20::xchacha::hchacha (6 samples, 0.19%)core::num::<impl u32>::from_le_bytes (1 samples, 0.03%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as crypto_common::KeyIvInit>::new (8 samples, 0.25%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::finalize (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::finalize (1 samples, 0.03%)poly1305::backend::soft::State::finalize_mut (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.03%)core::iter::traits::iterator::Iterator::fold (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.03%)core::slice::<impl [T]>::copy_from_slice (1 samples, 0.03%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (2 samples, 0.06%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.06%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.06%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.06%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (2 samples, 0.06%)core::iter::traits::iterator::Iterator::for_each::call::{{closure}} (1 samples, 0.03%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate::{{closure}} (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::authenticate_lengths (4 samples, 0.12%)universal_hash::UniversalHash::update (1 samples, 0.03%)<poly1305::Poly1305 as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<poly1305::backend::autodetect::State as universal_hash::UniversalHash>::update_with_backend (1 samples, 0.03%)<universal_hash::UniversalHash::update::Ctx<BS> as universal_hash::UhfClosure>::call (1 samples, 0.03%)chacha20::backends::sse2::double_quarter_round (4 samples, 0.12%)chacha20::backends::sse2::add_xor_rot (4 samples, 0.12%)core::core_arch::x86::sse2::_mm_add_epi32 (2 samples, 0.06%)cipher::stream::StreamCipher::apply_keystream (5 samples, 0.15%)cipher::stream::StreamCipher::try_apply_keystream (5 samples, 0.15%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (5 samples, 0.15%)cipher::stream_core::StreamCipherCore::write_keystream_block (5 samples, 0.15%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.15%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (5 samples, 0.15%)chacha20::backends::sse2::inner (5 samples, 0.15%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (5 samples, 0.15%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (5 samples, 0.15%)chacha20::backends::sse2::rounds (5 samples, 0.15%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.03%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.03%)core::mem::replace (1 samples, 0.03%)<Z as zeroize::Zeroize>::zeroize (1 samples, 0.03%)core::ptr::drop_in_place<cipher::stream_wrapper::StreamCipherCoreWrapper<chacha20::xchacha::XChaChaCore<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm,typenum::bit::B1>,typenum::bit::B0>,typenum::bit::B1>,typenum::bit::B0>>>> (2 samples, 0.06%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as core::ops::drop::Drop>::drop (2 samples, 0.06%)<[Z] as zeroize::Zeroize>::zeroize (1 samples, 0.03%)zeroize::volatile_set (1 samples, 0.03%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}} (1 samples, 0.03%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.06%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.06%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.06%)<core::slice::iter::IterMut<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)core::slice::iter::IterMut<T>::post_inc_start (1 samples, 0.03%)chacha20poly1305::cipher::Cipher<C>::encrypt_in_place_detached (15 samples, 0.46%)universal_hash::UniversalHash::update_padded (3 samples, 0.09%)generic_array::impls::<impl core::default::Default for generic_array::GenericArray<T,N>>::default (3 samples, 0.09%)<generic_array::GenericArray<T,N> as generic_array::sequence::GenericSequence<T>>::generate (3 samples, 0.09%)generic_array::ArrayBuilder<T,N>::into_inner (1 samples, 0.03%)core::mem::forget (1 samples, 0.03%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_slli_epi32 (1 samples, 0.03%)chacha20::backends::sse2::add_xor_rot (3 samples, 0.09%)core::core_arch::x86::sse2::_mm_xor_si128 (1 samples, 0.03%)cipher::stream::StreamCipher::apply_keystream (6 samples, 0.19%)cipher::stream::StreamCipher::try_apply_keystream (6 samples, 0.19%)<cipher::stream_wrapper::StreamCipherCoreWrapper<T> as cipher::stream::StreamCipher>::try_apply_keystream_inout (6 samples, 0.19%)cipher::stream_core::StreamCipherCore::write_keystream_block (6 samples, 0.19%)<chacha20::xchacha::XChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (6 samples, 0.19%)<chacha20::ChaChaCore<R> as cipher::stream_core::StreamCipherCore>::process_with_backend (6 samples, 0.19%)chacha20::backends::sse2::inner (6 samples, 0.19%)<cipher::stream_core::WriteBlockCtx<BS> as cipher::stream_core::StreamClosure>::call (5 samples, 0.15%)<chacha20::backends::sse2::Backend<R> as cipher::stream_core::StreamBackend>::gen_ks_block (5 samples, 0.15%)chacha20::backends::sse2::rounds (5 samples, 0.15%)chacha20::backends::sse2::double_quarter_round (4 samples, 0.12%)chacha20::backends::sse2::rows_to_cols (1 samples, 0.03%)core::core_arch::x86::sse2::_mm_shuffle_epi32 (1 samples, 0.03%)<chacha20poly1305::ChaChaPoly1305<C,N> as aead::AeadInPlace>::encrypt_in_place_detached (30 samples, 0.93%)chacha20poly1305::cipher::Cipher<C>::new (7 samples, 0.22%)generic_array::GenericArray<T,N>::from_slice (1 samples, 0.03%)<T as core::convert::Into<U>>::into (1 samples, 0.03%)<&generic_array::GenericArray<T,N> as core::convert::From<&[T]>>::from (1 samples, 0.03%)tftp::server::server::write_block (47 samples, 1.46%)tftp::server::connection::Connection<R,W,S>::send_packet (33 samples, 1.02%)tftp::encryption::Encryptor::encrypt (31 samples, 0.96%)aead::AeadInPlace::encrypt_in_place (31 samples, 0.96%)<heapless::vec::Vec<u8,_> as aead::Buffer>::extend_from_slice (1 samples, 0.03%)heapless::vec::Vec<T,_>::extend_from_slice (1 samples, 0.03%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.03%)tftp::server::validation::handle_file_size (1 samples, 0.03%)core::ops::function::FnOnce::call_once (1 samples, 0.03%)tftp::instant_callback::{{closure}} (1 samples, 0.03%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (1 samples, 0.03%)clock_gettime (1 samples, 0.03%)all (3,229 samples, 100%)tftp (3,229 samples, 100.00%)tftp[unknown] (3,219 samples, 99.69%)[unknown]tftp::server::server::server (3,209 samples, 99.38%)tftp::server::server::servertftp::std_compat::time::Instant::elapsed (2 samples, 0.06%)core::time::Duration::from_micros (1 samples, 0.03%)core::time::Duration::new (1 samples, 0.03%)core::num::<impl u64>::checked_add (1 samples, 0.03%) \ No newline at end of file diff --git a/info/server_flamegraph_no_encryption_alloc.svg b/info/server_flamegraph_no_encryption_alloc.svg new file mode 100644 index 0000000..b25af47 --- /dev/null +++ b/info/server_flamegraph_no_encryption_alloc.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [[stack]] (1 samples, 0.33%)recvfrom (1 samples, 0.33%)[unknown] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (2 samples, 0.66%)[ld-linux-x86-64.so.2] (2 samples, 0.66%)[ld-linux-x86-64.so.2] (2 samples, 0.66%)[ld-linux-x86-64.so.2] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (1 samples, 0.33%)[ld-linux-x86-64.so.2] (7 samples, 2.31%)[..[unknown] (1 samples, 0.33%)<tftp::cli::ClientCliConfig as clap::derive::Args>::augment_args (1 samples, 0.33%)<once_cell::sync::Lazy<T,F> as core::ops::deref::Deref>::deref (1 samples, 0.33%)once_cell::sync::Lazy<T,F>::force (1 samples, 0.33%)once_cell::sync::OnceCell<T>::get_or_init (1 samples, 0.33%)once_cell::sync::OnceCell<T>::get_or_try_init (1 samples, 0.33%)once_cell::sync::OnceCell<T>::get (1 samples, 0.33%)[libc.so.6] (1 samples, 0.33%)main (1 samples, 0.33%)std::rt::lang_start (1 samples, 0.33%)std::rt::lang_start_internal (1 samples, 0.33%)std::panic::catch_unwind (1 samples, 0.33%)std::panicking::try (1 samples, 0.33%)std::panicking::try::do_call (1 samples, 0.33%)std::rt::lang_start_internal::{{closure}} (1 samples, 0.33%)std::panic::catch_unwind (1 samples, 0.33%)std::panicking::try (1 samples, 0.33%)std::panicking::try::do_call (1 samples, 0.33%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (1 samples, 0.33%)std::rt::lang_start::{{closure}} (1 samples, 0.33%)std::sys_common::backtrace::__rust_begin_short_backtrace (1 samples, 0.33%)core::ops::function::FnOnce::call_once (1 samples, 0.33%)tftp::main (1 samples, 0.33%)tftp::server::server::server (1 samples, 0.33%)tftp::server::server::write_block (1 samples, 0.33%)tftp::server::connection::Connection<R,W,S>::send_packet (1 samples, 0.33%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (1 samples, 0.33%)tftp::socket::socket_addr_to_std (1 samples, 0.33%)std::net::socket_addr::SocketAddrV4::new (1 samples, 0.33%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (2 samples, 0.66%)polling::Poller::wait (2 samples, 0.66%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (2 samples, 0.66%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (2 samples, 0.66%)alloc::vec::Vec<T,A>::extend_desugared (2 samples, 0.66%)alloc::vec::Vec<T,A>::reserve (2 samples, 0.66%)alloc::raw_vec::RawVec<T,A>::reserve (2 samples, 0.66%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (2 samples, 0.66%)alloc::raw_vec::RawVec<T,A>::grow_amortized (2 samples, 0.66%)alloc::raw_vec::finish_grow (2 samples, 0.66%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.33%)__libc_start_main (3 samples, 0.99%)[libc.so.6] (3 samples, 0.99%)main (3 samples, 0.99%)std::rt::lang_start (3 samples, 0.99%)std::rt::lang_start_internal (3 samples, 0.99%)std::panic::catch_unwind (3 samples, 0.99%)std::panicking::try (3 samples, 0.99%)std::panicking::try::do_call (3 samples, 0.99%)std::rt::lang_start_internal::{{closure}} (3 samples, 0.99%)std::panic::catch_unwind (3 samples, 0.99%)std::panicking::try (3 samples, 0.99%)std::panicking::try::do_call (3 samples, 0.99%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (3 samples, 0.99%)std::rt::lang_start::{{closure}} (3 samples, 0.99%)std::sys_common::backtrace::__rust_begin_short_backtrace (3 samples, 0.99%)core::ops::function::FnOnce::call_once (3 samples, 0.99%)tftp::main (3 samples, 0.99%)tftp::server::server::server (3 samples, 0.99%)tftp::server::server::write_block (1 samples, 0.33%)tftp::server::connection::Connection<R,W,S>::send_packet (1 samples, 0.33%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (1 samples, 0.33%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.33%)clap::parser::parser::Parser::get_matches_with (1 samples, 0.33%)clap::parser::parser::Parser::parse_subcommand (1 samples, 0.33%)clap::builder::command::Command::_build_subcommand (1 samples, 0.33%)clap::builder::command::Command::_build_self (1 samples, 0.33%)clap::builder::debug_asserts::assert_app (1 samples, 0.33%)clap::builder::debug_asserts::assert_arg (1 samples, 0.33%)core::slice::<impl [T]>::iter (1 samples, 0.33%)core::slice::iter::Iter<T>::new (1 samples, 0.33%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.33%)std::rt::lang_start::{{closure}} (1 samples, 0.33%)std::sys_common::backtrace::__rust_begin_short_backtrace (1 samples, 0.33%)core::ops::function::FnOnce::call_once (1 samples, 0.33%)tftp::main (1 samples, 0.33%)tftp::server::server::server (1 samples, 0.33%)tftp::server::server::write_block (1 samples, 0.33%)tftp::server::connection::Connection<R,W,S>::send_packet (1 samples, 0.33%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (1 samples, 0.33%)std::net::udp::UdpSocket::send_to (1 samples, 0.33%)<core::option::IntoIter<A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.33%)<core::option::Item<A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.33%)core::option::Option<T>::take (1 samples, 0.33%)core::mem::replace (1 samples, 0.33%)std::rt::lang_start (1 samples, 0.33%)std::rt::lang_start_internal (1 samples, 0.33%)std::panic::catch_unwind (1 samples, 0.33%)std::panicking::try (1 samples, 0.33%)std::panicking::try::do_call (1 samples, 0.33%)std::rt::lang_start_internal::{{closure}} (1 samples, 0.33%)std::panic::catch_unwind (1 samples, 0.33%)std::panicking::try (1 samples, 0.33%)std::panicking::try::do_call (1 samples, 0.33%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (1 samples, 0.33%)std::rt::lang_start::{{closure}} (1 samples, 0.33%)std::sys_common::backtrace::__rust_begin_short_backtrace (1 samples, 0.33%)core::ops::function::FnOnce::call_once (1 samples, 0.33%)tftp::main (1 samples, 0.33%)tftp::server::server::server (1 samples, 0.33%)tftp::server::server::write_block (1 samples, 0.33%)tftp::server::connection::Connection<R,W,S>::send_packet (1 samples, 0.33%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (1 samples, 0.33%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (1 samples, 0.33%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.33%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (1 samples, 0.33%)alloc::alloc::dealloc (1 samples, 0.33%)cfree (1 samples, 0.33%)[libc.so.6] (1 samples, 0.33%)__rdl_alloc (1 samples, 0.33%)alloc::alloc::alloc (3 samples, 0.99%)malloc (2 samples, 0.66%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (5 samples, 1.65%)polling::Poller::wait (5 samples, 1.65%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (5 samples, 1.65%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (5 samples, 1.65%)alloc::vec::Vec<T,A>::extend_desugared (5 samples, 1.65%)alloc::vec::Vec<T,A>::reserve (5 samples, 1.65%)alloc::raw_vec::RawVec<T,A>::reserve (5 samples, 1.65%)alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (5 samples, 1.65%)alloc::raw_vec::RawVec<T,A>::grow_amortized (5 samples, 1.65%)alloc::raw_vec::finish_grow (5 samples, 1.65%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (5 samples, 1.65%)alloc::alloc::Global::alloc_impl (5 samples, 1.65%)core::ptr::non_null::NonNull<T>::new (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.33%)<core::option::Option<T> as core::ops::try_trait::Try>::branch (1 samples, 0.33%)tftp::server::server::send_data_blocks (4 samples, 1.32%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain (4 samples, 1.32%)core::ptr::drop_in_place<alloc::collections::btree::map::DrainFilter<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>,alloc::collections::btree::map::BTreeMap<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>>::retain<tftp::server::server::send_data_blocks<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>::{{closure}}>::{{closure}}>> (4 samples, 1.32%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::ops::drop::Drop>::drop (4 samples, 1.32%)core::iter::traits::iterator::Iterator::for_each (4 samples, 1.32%)core::iter::traits::iterator::Iterator::fold (4 samples, 1.32%)<&mut I as core::iter::traits::iterator::Iterator>::next (4 samples, 1.32%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::iter::traits::iterator::Iterator>::next (4 samples, 1.32%)alloc::collections::btree::map::DrainFilterInner<K,V>::next (4 samples, 1.32%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain::{{closure}} (1 samples, 0.33%)std::rt::lang_start_internal (13 samples, 4.29%)std::..std::panic::catch_unwind (13 samples, 4.29%)std::..std::panicking::try (13 samples, 4.29%)std::..std::panicking::try::do_call (13 samples, 4.29%)std::..std::rt::lang_start_internal::{{closure}} (13 samples, 4.29%)std::..std::panic::catch_unwind (13 samples, 4.29%)std::..std::panicking::try (13 samples, 4.29%)std::..std::panicking::try::do_call (13 samples, 4.29%)std::..core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (13 samples, 4.29%)core:..std::rt::lang_start::{{closure}} (13 samples, 4.29%)std::..std::sys_common::backtrace::__rust_begin_short_backtrace (13 samples, 4.29%)std::..core::ops::function::FnOnce::call_once (13 samples, 4.29%)core:..tftp::main (13 samples, 4.29%)tftp:..tftp::server::server::server (13 samples, 4.29%)tftp:..tftp::server::server::write_block (4 samples, 1.32%)tftp::server::connection::Connection<R,W,S>::send_packet (4 samples, 1.32%)<tftp::socket::StdSocket as tftp::socket::Socket>::send_to (4 samples, 1.32%)std::net::udp::UdpSocket::send_to (4 samples, 1.32%)std::sys_common::net::UdpSocket::send_to (4 samples, 1.32%)sendto (4 samples, 1.32%)alloc::collections::btree::navigate::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,alloc::collections::btree::node::marker::KV>>::next_leaf_edge (3 samples, 0.99%)std::sys_common::backtrace::__rust_begin_short_backtrace (4 samples, 1.32%)core::ops::function::FnOnce::call_once (4 samples, 1.32%)tftp::main (4 samples, 1.32%)tftp::server::server::server (4 samples, 1.32%)tftp::server::server::send_data_blocks (4 samples, 1.32%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain (4 samples, 1.32%)core::ptr::drop_in_place<alloc::collections::btree::map::DrainFilter<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>,alloc::collections::btree::map::BTreeMap<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>>::retain<tftp::server::server::send_data_blocks<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>::{{closure}}>::{{closure}}>> (4 samples, 1.32%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::ops::drop::Drop>::drop (4 samples, 1.32%)core::iter::traits::iterator::Iterator::for_each (4 samples, 1.32%)core::iter::traits::iterator::Iterator::fold (4 samples, 1.32%)<&mut I as core::iter::traits::iterator::Iterator>::next (4 samples, 1.32%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::iter::traits::iterator::Iterator>::next (4 samples, 1.32%)alloc::collections::btree::map::DrainFilterInner<K,V>::next (4 samples, 1.32%)core::option::Option<T>::take (1 samples, 0.33%)core::mem::replace (1 samples, 0.33%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::retain::{{closure}} (2 samples, 0.66%)tftp::server::server::send_data_blocks::{{closure}} (2 samples, 0.66%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.33%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.33%)core::mem::replace (1 samples, 0.33%)core::ptr::read (1 samples, 0.33%)core::mem::maybe_uninit::MaybeUninit<T>::assume_init (1 samples, 0.33%)core::mem::manually_drop::ManuallyDrop<T>::into_inner (1 samples, 0.33%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::Edge>::right_kv (1 samples, 0.33%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::KV>::new_kv (1 samples, 0.33%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>::forget_node_type (1 samples, 0.33%)alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::Leaf>::forget_type (1 samples, 0.33%)alloc::collections::btree::navigate::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::Leaf>,alloc::collections::btree::node::marker::Edge>>::next_kv (3 samples, 0.99%)alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>::ascend (1 samples, 0.33%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::KV>::right_edge (1 samples, 0.33%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,NodeType>,alloc::collections::btree::node::marker::Edge>::new_edge (1 samples, 0.33%)alloc::collections::btree::navigate::<impl alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,alloc::collections::btree::node::marker::KV>>::next_leaf_edge (3 samples, 0.99%)alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>,Type>::force (2 samples, 0.66%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,Type>::as_leaf_mut (2 samples, 0.66%)tftp::server::server::send_data_blocks (12 samples, 3.96%)tftp..alloc::collections::btree::map::BTreeMap<K,V,A>::retain (12 samples, 3.96%)allo..core::ptr::drop_in_place<alloc::collections::btree::map::DrainFilter<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>,alloc::collections::btree::map::BTreeMap<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>>::retain<tftp::server::server::send_data_blocks<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>::{{closure}}>::{{closure}}>> (12 samples, 3.96%)core..<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::ops::drop::Drop>::drop (12 samples, 3.96%)<all..core::iter::traits::iterator::Iterator::for_each (12 samples, 3.96%)core..core::iter::traits::iterator::Iterator::fold (12 samples, 3.96%)core..<&mut I as core::iter::traits::iterator::Iterator>::next (12 samples, 3.96%)<&mu..<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::iter::traits::iterator::Iterator>::next (12 samples, 3.96%)<all..alloc::collections::btree::map::DrainFilterInner<K,V>::next (12 samples, 3.96%)allo..alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut,K,V,NodeType>,alloc::collections::btree::node::marker::KV>::kv_mut (4 samples, 1.32%)core::slice::<impl [T]>::get_unchecked_mut (2 samples, 0.66%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked_mut (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.33%)alloc::vec::Vec<T,A>::reserve (1 samples, 0.33%)alloc::raw_vec::RawVec<T,A>::reserve (1 samples, 0.33%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (1 samples, 0.33%)core::iter::traits::iterator::Iterator::try_fold (1 samples, 0.33%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (1 samples, 0.33%)core::ops::function::Fn::call (1 samples, 0.33%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (1 samples, 0.33%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (1 samples, 0.33%)<tftp::packet::AckPacket as tftp::packet::ByteConverter>::to_bytes (3 samples, 0.99%)core::iter::traits::iterator::Iterator::collect (3 samples, 0.99%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (3 samples, 0.99%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (3 samples, 0.99%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (3 samples, 0.99%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (3 samples, 0.99%)alloc::vec::Vec<T,A>::extend_trusted (3 samples, 0.99%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.66%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.66%)core::ptr::drop_in_place<core::iter::traits::iterator::Iterator::for_each::call<u8,alloc::vec::Vec<u8>::extend_trusted<core::array::iter::IntoIter<u8,2_usize>>::{{closure}}>::{{closure}}> (1 samples, 0.33%)core::array::iter::<impl core::iter::traits::collect::IntoIterator for [T: N]>::into_iter (1 samples, 0.33%)<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.33%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (2 samples, 0.66%)alloc::vec::Vec<T,A>::extend_trusted (2 samples, 0.66%)core::iter::traits::iterator::Iterator::for_each (2 samples, 0.66%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.66%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.66%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u8>> (1 samples, 0.33%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.33%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u8,alloc::alloc::Global>> (1 samples, 0.33%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (1 samples, 0.33%)tftp::main (21 samples, 6.93%)tftp::maintftp::server::server::server (21 samples, 6.93%)tftp::ser..tftp::server::server::write_block (9 samples, 2.97%)tft..tftp::server::connection::Connection<R,W,S>::send_packet (9 samples, 2.97%)tft..<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (9 samples, 2.97%)<tf..core::iter::traits::iterator::Iterator::collect (5 samples, 1.65%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (5 samples, 1.65%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (5 samples, 1.65%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (5 samples, 1.65%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::size_hint (3 samples, 0.99%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::size_hint (1 samples, 0.33%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.66%)<core::iter::adapters::by_ref_sized::ByRefSized<I> as core::iter::traits::iterator::Iterator>::fold (2 samples, 0.66%)core::iter::traits::iterator::Iterator::try_fold (2 samples, 0.66%)<core::const_closure::ConstFnMutClosure<&mut A,Function> as core::ops::function::FnMut<ClosureArguments>>::call_mut (2 samples, 0.66%)core::ops::function::Fn::call (2 samples, 0.66%)core::ops::try_trait::NeverShortCircuit<T>::wrap_mut_2_imp (2 samples, 0.66%)<core::array::iter::IntoIter<T,_> as core::iter::traits::iterator::Iterator>::fold::{{closure}} (2 samples, 0.66%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.33%)<usize as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.33%)core::ptr::const_ptr::<impl *const T>::add (1 samples, 0.33%)[unknown] (50 samples, 16.50%)[unknown]tftp::server::server::server (4 samples, 1.32%)tftp::server::server::write_block (4 samples, 1.32%)tftp::server::connection::Connection<R,W,S>::send_packet (4 samples, 1.32%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (4 samples, 1.32%)core::iter::traits::iterator::Iterator::collect (4 samples, 1.32%)<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (4 samples, 1.32%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (4 samples, 1.32%)<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (4 samples, 1.32%)<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (4 samples, 1.32%)alloc::vec::Vec<T,A>::extend_trusted (4 samples, 1.32%)core::iter::traits::iterator::Iterator::for_each (4 samples, 1.32%)<core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::fold (4 samples, 1.32%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.66%)core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<u8>> (2 samples, 0.66%)<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.66%)core::ptr::drop_in_place<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<u8,alloc::alloc::Global>> (2 samples, 0.66%)<<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.66%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (2 samples, 0.66%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.66%)alloc::raw_vec::RawVec<T,A>::current_memory (2 samples, 0.66%)core::result::Result<T,E>::unwrap_unchecked (1 samples, 0.33%)clap::derive::Parser::parse (1 samples, 0.33%)<tftp::cli::Args as clap::derive::FromArgMatches>::from_arg_matches_mut (1 samples, 0.33%)clap::parser::matches::arg_matches::ArgMatches::remove_one (1 samples, 0.33%)clap::parser::matches::arg_matches::ArgMatches::try_remove_one (1 samples, 0.33%)clap::parser::matches::arg_matches::ArgMatches::try_remove_arg_t (1 samples, 0.33%)clap::parser::matches::matched_arg::MatchedArg::infer_type_id (1 samples, 0.33%)<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (4 samples, 1.32%)core::slice::raw::from_raw_parts (2 samples, 0.66%)core::ptr::slice_from_raw_parts (2 samples, 0.66%)core::ptr::metadata::from_raw_parts (2 samples, 0.66%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (4 samples, 1.32%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 0.66%)core::slice::<impl [T]>::get (1 samples, 0.33%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.33%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.33%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.33%)core::ptr::slice_from_raw_parts (1 samples, 0.33%)core::ptr::metadata::from_raw_parts (1 samples, 0.33%)<tftp::packet::DataPacket as tftp::packet::ByteConverter>::from_bytes (6 samples, 1.98%)<..tftp::packet::try_from (4 samples, 1.32%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.33%)[libc.so.6] (1 samples, 0.33%)core::slice::<impl [T]>::get (1 samples, 0.33%)memcpy (1 samples, 0.33%)<T as core::convert::TryInto<U>>::try_into (1 samples, 0.33%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (1 samples, 0.33%)core::result::Result<T,E>::map (1 samples, 0.33%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.33%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (13 samples, 4.29%)<tftp..tftp::packet::PacketType::from_bytes (2 samples, 0.66%)tftp::packet::try_from (2 samples, 0.66%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.33%)<alloc::vec::Vec<T,A> as core::ops::drop::Drop>::drop (2 samples, 0.66%)alloc::vec::Vec<T,A>::as_mut_ptr (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::is_null (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl (1 samples, 0.33%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (7 samples, 2.31%)c..core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (5 samples, 1.65%)<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (5 samples, 1.65%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (4 samples, 1.32%)alloc::alloc::dealloc (2 samples, 0.66%)cfree (2 samples, 0.66%)[libc.so.6] (2 samples, 0.66%)core::result::Result<T,E>::map (1 samples, 0.33%)core::ptr::drop_in_place<std::io::error::Error> (2 samples, 0.66%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.33%)core::result::Result<T,E>::map_err (10 samples, 3.30%)cor..core::ops::function::FnOnce::call_once (8 samples, 2.64%)co..tftp::io::from_io_err (7 samples, 2.31%)t..std::io::error::Error::kind (5 samples, 1.65%)std::io::error::repr_bitpacked::Repr::data (2 samples, 0.66%)std::io::error::repr_bitpacked::decode_repr (2 samples, 0.66%)polling::Event::readable (1 samples, 0.33%)<&T as polling::Source>::raw (2 samples, 0.66%)std::os::fd::net::<impl std::os::fd::raw::AsRawFd for std::net::udp::UdpSocket>::as_raw_fd (1 samples, 0.33%)log::max_level (3 samples, 0.99%)core::sync::atomic::AtomicUsize::load (3 samples, 0.99%)core::sync::atomic::atomic_load (2 samples, 0.66%)polling::Poller::modify (9 samples, 2.97%)pol..polling::epoll::Poller::modify (7 samples, 2.31%)p..polling::epoll::Poller::ctl (4 samples, 1.32%)core::option::Option<T>::map (4 samples, 1.32%)polling::epoll::Poller::ctl::{{closure}} (1 samples, 0.33%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.33%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.33%)core::slice::iter::Iter<T>::post_inc_start (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.33%)core::ptr::mut_ptr::<impl *mut T>::offset (1 samples, 0.33%)<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold (2 samples, 0.66%)core::iter::traits::iterator::Iterator::try_fold (2 samples, 0.66%)core::iter::adapters::map::map_try_fold::{{closure}} (1 samples, 0.33%)polling::epoll::Events::iter::{{closure}} (1 samples, 0.33%)<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (6 samples, 1.98%)<..core::iter::traits::iterator::Iterator::find (6 samples, 1.98%)c..core::ops::control_flow::ControlFlow<B,C>::break_value (3 samples, 0.99%)alloc::raw_vec::RawVec<T,A>::needs_to_grow (1 samples, 0.33%)core::alloc::layout::Layout::array (1 samples, 0.33%)core::alloc::layout::Layout::array::inner (1 samples, 0.33%)core::alloc::layout::Layout::max_size_for_align (1 samples, 0.33%)core::cmp::max (3 samples, 0.99%)core::cmp::Ord::max (3 samples, 0.99%)core::cmp::max_by (2 samples, 0.66%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (15 samples, 4.95%)<alloc..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (14 samples, 4.62%)<allo..alloc::vec::Vec<T,A>::extend_desugared (14 samples, 4.62%)alloc..alloc::vec::Vec<T,A>::reserve (7 samples, 2.31%)a..alloc::raw_vec::RawVec<T,A>::reserve (7 samples, 2.31%)a..alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (5 samples, 1.65%)alloc::raw_vec::RawVec<T,A>::grow_amortized (5 samples, 1.65%)core::option::Option<T>::ok_or (1 samples, 0.33%)<std::sync::mutex::MutexGuard<T> as core::ops::deref::Deref>::deref (1 samples, 0.33%)<std::sync::mutex::MutexGuard<T> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.33%)core::sync::atomic::AtomicBool::swap (2 samples, 0.66%)core::sync::atomic::atomic_swap (1 samples, 0.33%)log::max_level (1 samples, 0.33%)core::sync::atomic::AtomicUsize::load (1 samples, 0.33%)core::sync::atomic::atomic_load (1 samples, 0.33%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (2 samples, 0.66%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (2 samples, 0.66%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.33%)polling::epoll::Events::iter (4 samples, 1.32%)core::slice::<impl [T]>::iter (2 samples, 0.66%)core::slice::iter::Iter<T>::new (2 samples, 0.66%)core::ptr::const_ptr::<impl *const T>::is_null (1 samples, 0.33%)core::ptr::const_ptr::<impl *const T>::is_null::runtime_impl (1 samples, 0.33%)core::ptr::const_ptr::<impl *const T>::addr (1 samples, 0.33%)<T as core::convert::Into<U>>::into (1 samples, 0.33%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (3 samples, 0.99%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (2 samples, 0.66%)[libc.so.6] (4 samples, 1.32%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (5 samples, 1.65%)core::ptr::drop_in_place<std::io::error::Error> (5 samples, 1.65%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (2 samples, 0.66%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (2 samples, 0.66%)std::io::error::repr_bitpacked::decode_repr (2 samples, 0.66%)core::time::Duration::as_secs (1 samples, 0.33%)core::time::Duration::from_secs (1 samples, 0.33%)core::time::Duration::new (1 samples, 0.33%)core::num::<impl u64>::checked_add (1 samples, 0.33%)core::time::Duration::subsec_nanos (1 samples, 0.33%)epoll_wait (13 samples, 4.29%)epoll..core::option::Option<T>::map (2 samples, 0.66%)polling::epoll::Poller::ctl::{{closure}} (1 samples, 0.33%)polling::epoll::Poller::modify (5 samples, 1.65%)polling::epoll::Poller::ctl (3 samples, 0.99%)core::option::Option<T>::unwrap_or (1 samples, 0.33%)read (2 samples, 0.66%)[unknown] (1 samples, 0.33%)polling::epoll::Poller::wait (44 samples, 14.52%)polling::epoll::Poller..timerfd_settime (1 samples, 0.33%)std::sync::mutex::MutexGuard<T>::new (4 samples, 1.32%)std::sync::poison::Flag::guard (3 samples, 0.99%)std::sync::poison::Flag::get (2 samples, 0.66%)core::sync::atomic::AtomicBool::load (2 samples, 0.66%)core::sync::atomic::atomic_load (1 samples, 0.33%)polling::Poller::wait (76 samples, 25.08%)polling::Poller::waitstd::sync::mutex::Mutex<T>::try_lock (6 samples, 1.98%)s..std::sys::unix::locks::futex_mutex::Mutex::try_lock (1 samples, 0.33%)core::sync::atomic::AtomicU32::compare_exchange (1 samples, 0.33%)core::sync::atomic::atomic_compare_exchange (1 samples, 0.33%)recvfrom (2 samples, 0.66%)<isize as std::sys::unix::IsMinusOne>::is_minus_one (1 samples, 0.33%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (111 samples, 36.63%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_fromstd::net::udp::UdpSocket::recv_from (5 samples, 1.65%)std::sys_common::net::UdpSocket::recv_from (5 samples, 1.65%)std::sys::unix::net::Socket::recv_from (5 samples, 1.65%)std::sys::unix::net::Socket::recv_from_with_flags (5 samples, 1.65%)std::sys::unix::cvt (2 samples, 0.66%)std::io::error::Error::last_os_error (1 samples, 0.33%)std::sys::unix::os::errno (1 samples, 0.33%)__errno_location (1 samples, 0.33%)<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next (3 samples, 0.99%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next (1 samples, 0.33%)core::array::<impl core::ops::index::Index<I> for [T: N]>::index (1 samples, 0.33%)core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (1 samples, 0.33%)<core::ops::range::RangeFull as core::slice::index::SliceIndex<[T]>>::index (1 samples, 0.33%)<tftp::std_compat::net::SocketAddr as core::cmp::Ord>::cmp (11 samples, 3.63%)<tft..<tftp::std_compat::net::IpVersion as core::cmp::Ord>::cmp (9 samples, 2.97%)<tf..core::array::<impl core::cmp::Ord for [T: N]>::cmp (6 samples, 1.98%)c..core::cmp::impls::<impl core::cmp::Ord for &A>::cmp (3 samples, 0.99%)core::slice::cmp::<impl core::cmp::Ord for [T]>::cmp (3 samples, 0.99%)<u8 as core::slice::cmp::SliceOrd>::compare (2 samples, 0.66%)core::cmp::impls::<impl core::cmp::Ord for isize>::cmp (1 samples, 0.33%)alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut,K,V,Type>::keys (1 samples, 0.33%)core::slice::<impl [T]>::get_unchecked (1 samples, 0.33%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::entry (23 samples, 7.59%)alloc::col..alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::search_tree (20 samples, 6.60%)alloc::co..alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::search_node (19 samples, 6.27%)alloc::c..alloc::collections::btree::search::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>>::find_key_index (18 samples, 5.94%)alloc::c..core::slice::<impl [T]>::iter (1 samples, 0.33%)core::slice::iter::Iter<T>::new (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::is_empty (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::len (1 samples, 0.33%)alloc::collections::btree::map::entry::OccupiedEntry<K,V,A>::get_mut (1 samples, 0.33%)alloc::vec::Vec<T,A>::resize (2 samples, 0.66%)alloc::vec::Vec<T,A>::extend_with (1 samples, 0.33%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.33%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.33%)alloc::vec::Vec<T,A>::truncate (1 samples, 0.33%)core::cmp::PartialOrd::gt (1 samples, 0.33%)<core::time::Duration as core::cmp::PartialOrd>::partial_cmp (1 samples, 0.33%)core::ptr::drop_in_place<core::result::Result<(),tftp::packet::ErrorPacket>> (1 samples, 0.33%)core::slice::<impl [T]>::len (1 samples, 0.33%)core::time::Duration::from_millis (3 samples, 0.99%)core::time::Duration::new (2 samples, 0.66%)core::num::<impl u64>::checked_add (2 samples, 0.66%)core::time::Duration::from_secs (1 samples, 0.33%)core::time::Duration::new (1 samples, 0.33%)log::max_level (2 samples, 0.66%)core::sync::atomic::AtomicUsize::load (2 samples, 0.66%)core::sync::atomic::atomic_load (2 samples, 0.66%)core::ops::function::FnOnce::call_once (9 samples, 2.97%)cor..tftp::instant_callback::{{closure}} (6 samples, 1.98%)t..std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (3 samples, 0.99%)clock_gettime (3 samples, 0.99%)__vdso_clock_gettime (3 samples, 0.99%)tftp::instant_callback (12 samples, 3.96%)tftp..tftp::std_compat::time::Instant::from_time (12 samples, 3.96%)tftp..core::time::Duration::from_micros (2 samples, 0.66%)core::time::Duration::new (2 samples, 0.66%)core::num::<impl u64>::checked_add (1 samples, 0.33%)core::num::<impl u64>::overflowing_add (1 samples, 0.33%)<T as core::convert::TryInto<U>>::try_into (4 samples, 1.32%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from (4 samples, 1.32%)core::result::Result<T,E>::map (3 samples, 0.99%)core::array::<impl core::convert::TryFrom<&[T]> for [T: N]>::try_from::{{closure}} (1 samples, 0.33%)core::option::Option<T>::ok_or (2 samples, 0.66%)core::ptr::drop_in_place<tftp::error::PacketError> (2 samples, 0.66%)tftp::packet::PacketType::from_bytes (10 samples, 3.30%)tft..tftp::packet::try_from (9 samples, 2.97%)tft..core::slice::<impl [T]>::get (2 samples, 0.66%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (2 samples, 0.66%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (2 samples, 0.66%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (1 samples, 0.33%)[libc.so.6] (1 samples, 0.33%)alloc::collections::btree::borrow::DormantMutRef<T>::new (1 samples, 0.33%)alloc::collections::btree::node::NodeRef<BorrowType,K,V,Type>::first_edge (1 samples, 0.33%)alloc::collections::btree::navigate::<impl alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>>::first_leaf_edge (2 samples, 0.66%)alloc::collections::btree::node::NodeRef<BorrowType,K,V,alloc::collections::btree::node::marker::LeafOrInternal>::force (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::drain_filter_inner (4 samples, 1.32%)memcpy (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::drain_filter (7 samples, 2.31%)a..memcpy (1 samples, 0.33%)tftp::server::server::send_data_blocks (12 samples, 3.96%)tftp..alloc::collections::btree::map::BTreeMap<K,V,A>::retain (12 samples, 3.96%)allo..core::ptr::drop_in_place<alloc::collections::btree::map::DrainFilter<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>,alloc::collections::btree::map::BTreeMap<tftp::std_compat::net::SocketAddr,tftp::server::connection::Connection<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>>::retain<tftp::server::server::send_data_blocks<tftp::io::StdCompatFile,tftp::io::StdCompatFile,tftp::socket::StdSocket>::{{closure}}>::{{closure}}>> (5 samples, 1.65%)<alloc::collections::btree::map::DrainFilter<K,V,F,A> as core::ops::drop::Drop>::drop (5 samples, 1.65%)core::iter::traits::iterator::Iterator::for_each (5 samples, 1.65%)core::iter::traits::iterator::Iterator::fold (2 samples, 0.66%)<&mut I as core::iter::traits::iterator::Iterator>::next (1 samples, 0.33%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.33%)core::result::Result<T,E>::map_err (1 samples, 0.33%)<tftp::io::StdCompatFile as tftp::std_compat::io::Write>::write (4 samples, 1.32%)std::os::unix::net::datagram::UnixDatagram::send (1 samples, 0.33%)std::sys::unix::net::Socket::write (1 samples, 0.33%)std::sys::unix::fd::FileDesc::write (1 samples, 0.33%)write (1 samples, 0.33%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove_entry (3 samples, 0.99%)alloc::collections::btree::borrow::DormantMutRef<T>::new (3 samples, 0.99%)alloc::collections::btree::map::BTreeMap<K,V,A>::remove (4 samples, 1.32%)core::option::Option<T>::map (1 samples, 0.33%)<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (14 samples, 4.62%)<tftp..tftp::storage::BlockMapper::index (2 samples, 0.66%)tftp::server::server::write_block (20 samples, 6.60%)tftp::ser..tftp::server::connection::Connection<R,W,S>::send_packet (2 samples, 0.66%)core::ptr::drop_in_place<alloc::vec::Vec<u8>> (2 samples, 0.66%)core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8>> (1 samples, 0.33%)core::ops::function::FnOnce::call_once (5 samples, 1.65%)tftp::instant_callback::{{closure}} (4 samples, 1.32%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (2 samples, 0.66%)clock_gettime (2 samples, 0.66%)__vdso_clock_gettime (2 samples, 0.66%)all (303 samples, 100%)tftp (303 samples, 100.00%)tftp_start (245 samples, 80.86%)_start__libc_start_main (245 samples, 80.86%)__libc_start_main[libc.so.6] (245 samples, 80.86%)[libc.so.6]main (245 samples, 80.86%)mainstd::rt::lang_start (245 samples, 80.86%)std::rt::lang_startstd::rt::lang_start_internal (245 samples, 80.86%)std::rt::lang_start_internalstd::panic::catch_unwind (245 samples, 80.86%)std::panic::catch_unwindstd::panicking::try (245 samples, 80.86%)std::panicking::trystd::panicking::try::do_call (245 samples, 80.86%)std::panicking::try::do_callstd::rt::lang_start_internal::{{closure}} (245 samples, 80.86%)std::rt::lang_start_internal::{{closure}}std::panic::catch_unwind (245 samples, 80.86%)std::panic::catch_unwindstd::panicking::try (245 samples, 80.86%)std::panicking::trystd::panicking::try::do_call (245 samples, 80.86%)std::panicking::try::do_callcore::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (245 samples, 80.86%)core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_oncestd::rt::lang_start::{{closure}} (245 samples, 80.86%)std::rt::lang_start::{{closure}}std::sys_common::backtrace::__rust_begin_short_backtrace (245 samples, 80.86%)std::sys_common::backtrace::__rust_begin_short_backtracecore::ops::function::FnOnce::call_once (245 samples, 80.86%)core::ops::function::FnOnce::call_oncetftp::main (245 samples, 80.86%)tftp::maintftp::server::server::server (244 samples, 80.53%)tftp::server::server::servertftp::std_compat::time::Instant::elapsed (8 samples, 2.64%)tf..core::time::Duration::from_micros (2 samples, 0.66%)core::time::Duration::new (2 samples, 0.66%)core::num::<impl u64>::checked_add (2 samples, 0.66%)core::num::<impl u64>::overflowing_add (1 samples, 0.33%) \ No newline at end of file diff --git a/info/server_flamegraph_no_encryption_stack.svg b/info/server_flamegraph_no_encryption_stack.svg new file mode 100644 index 0000000..bebbcf7 --- /dev/null +++ b/info/server_flamegraph_no_encryption_stack.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch [[stack]] (1 samples, 0.82%)recvfrom (1 samples, 0.82%)[unknown] (1 samples, 0.82%)[ld-linux-x86-64.so.2] (1 samples, 0.82%)[ld-linux-x86-64.so.2] (1 samples, 0.82%)[ld-linux-x86-64.so.2] (1 samples, 0.82%)[ld-linux-x86-64.so.2] (6 samples, 4.92%)[ld-li..[unknown] (1 samples, 0.82%)core::iter::traits::iterator::Iterator::collect (2 samples, 1.64%)<heapless::vec::Vec<T,_> as core::iter::traits::collect::FromIterator<T>>::from_iter (2 samples, 1.64%)core::ptr::drop_in_place<core::iter::adapters::chain::Chain<core::array::iter::IntoIter<u8,2_usize>,heapless::vec::IntoIter<u8,1420_usize>>> (1 samples, 0.82%)core::ptr::drop_in_place<core::option::Option<heapless::vec::IntoIter<u8,1420_usize>>> (1 samples, 0.82%)core::ptr::drop_in_place<heapless::vec::IntoIter<u8,1420_usize>> (1 samples, 0.82%)<heapless::vec::IntoIter<T,_> as core::ops::drop::Drop>::drop (1 samples, 0.82%)core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut (1 samples, 0.82%)<core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index_mut (1 samples, 0.82%)<tftp::packet::Packet as tftp::packet::ByteConverter>::to_bytes (3 samples, 2.46%)<t..tftp::packet::PacketType::to_bytes (1 samples, 0.82%)__rust_probestack (1 samples, 0.82%)<tftp::packet::Packet as tftp::packet::ByteConverter>::from_bytes (3 samples, 2.46%)<t..core::slice::<impl [T]>::get (1 samples, 0.82%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.82%)<heapless::vec::Vec<T,_> as core::ops::deref::DerefMut>::deref_mut (1 samples, 0.82%)heapless::vec::Vec<T,_>::as_mut_slice (1 samples, 0.82%)<alloc::alloc::Global as core::alloc::Allocator>::deallocate (2 samples, 1.64%)alloc::alloc::dealloc (2 samples, 1.64%)cfree (2 samples, 1.64%)[libc.so.6] (2 samples, 1.64%)core::ptr::drop_in_place<alloc::vec::Vec<polling::Event>> (5 samples, 4.10%)core..core::ptr::drop_in_place<alloc::raw_vec::RawVec<polling::Event>> (4 samples, 3.28%)cor..<alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop (4 samples, 3.28%)<al..alloc::raw_vec::RawVec<T,A>::current_memory (2 samples, 1.64%)core::alloc::layout::Layout::array (1 samples, 0.82%)core::alloc::layout::Layout::array::inner (1 samples, 0.82%)core::result::Result<T,E>::map (1 samples, 0.82%)memcpy (1 samples, 0.82%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.82%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.82%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.82%)core::result::Result<T,E>::map_err (3 samples, 2.46%)co..core::ops::function::FnOnce::call_once (2 samples, 1.64%)tftp::io::from_io_err (2 samples, 1.64%)std::io::error::Error::kind (1 samples, 0.82%)log::max_level (1 samples, 0.82%)core::sync::atomic::AtomicUsize::load (1 samples, 0.82%)core::sync::atomic::atomic_load (1 samples, 0.82%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.82%)polling::Poller::modify (4 samples, 3.28%)pol..polling::epoll::Poller::modify (4 samples, 3.28%)pol..polling::epoll::Poller::ctl (3 samples, 2.46%)po..core::option::Option<T>::map (2 samples, 1.64%)polling::epoll::Poller::ctl::{{closure}} (1 samples, 0.82%)polling::epoll::read_flags (1 samples, 0.82%)<alloc::alloc::Global as core::alloc::Allocator>::allocate (1 samples, 0.82%)alloc::alloc::Global::alloc_impl (1 samples, 0.82%)alloc::alloc::alloc (1 samples, 0.82%)__rust_alloc (1 samples, 0.82%)alloc::raw_vec::finish_grow (2 samples, 1.64%)core::result::Result<T,E>::map_err (1 samples, 0.82%)core::cmp::max (1 samples, 0.82%)core::cmp::Ord::max (1 samples, 0.82%)core::cmp::max_by (1 samples, 0.82%)<alloc::vec::Vec<T,A> as core::iter::traits::collect::Extend<T>>::extend (6 samples, 4.92%)<alloc..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (6 samples, 4.92%)<alloc..alloc::vec::Vec<T,A>::extend_desugared (6 samples, 4.92%)alloc:..alloc::vec::Vec<T,A>::reserve (5 samples, 4.10%)allo..alloc::raw_vec::RawVec<T,A>::reserve (5 samples, 4.10%)allo..alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle (5 samples, 4.10%)allo..alloc::raw_vec::RawVec<T,A>::grow_amortized (5 samples, 4.10%)allo..core::num::<impl usize>::checked_add (1 samples, 0.82%)core::num::<impl usize>::overflowing_add (1 samples, 0.82%)alloc::vec::Vec<T,A>::len (1 samples, 0.82%)core::ptr::drop_in_place<std::sync::mutex::MutexGuard<polling::epoll::Events>> (1 samples, 0.82%)<std::sync::mutex::MutexGuard<T> as core::ops::drop::Drop>::drop (1 samples, 0.82%)std::sync::poison::Flag::done (1 samples, 0.82%)std::thread::panicking (1 samples, 0.82%)std::panicking::panicking (1 samples, 0.82%)std::panicking::panic_count::count_is_zero (1 samples, 0.82%)core::sync::atomic::AtomicUsize::load (1 samples, 0.82%)core::sync::atomic::atomic_load (1 samples, 0.82%)core::sync::atomic::AtomicBool::swap (2 samples, 1.64%)core::sync::atomic::atomic_swap (2 samples, 1.64%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (1 samples, 0.82%)[libc.so.6] (1 samples, 0.82%)core::ptr::drop_in_place<core::result::Result<isize,std::io::error::Error>> (1 samples, 0.82%)core::ptr::drop_in_place<std::io::error::Error> (1 samples, 0.82%)core::ptr::drop_in_place<std::io::error::repr_bitpacked::Repr> (1 samples, 0.82%)<std::io::error::repr_bitpacked::Repr as core::ops::drop::Drop>::drop (1 samples, 0.82%)epoll_wait (24 samples, 19.67%)epoll_waitlog::max_level (2 samples, 1.64%)core::sync::atomic::AtomicUsize::load (1 samples, 0.82%)polling::epoll::Poller::modify (2 samples, 1.64%)<log::Level as core::cmp::PartialOrd<log::LevelFilter>>::le (1 samples, 0.82%)polling::epoll::Poller::wait (35 samples, 28.69%)polling::epoll::Poller::waitstd::io::error::Error::last_os_error (2 samples, 1.64%)std::sys::unix::os::errno (2 samples, 1.64%)__errno_location (2 samples, 1.64%)std::sync::mutex::MutexGuard<T>::new (1 samples, 0.82%)std::sync::poison::Flag::guard (1 samples, 0.82%)std::thread::panicking (1 samples, 0.82%)std::panicking::panicking (1 samples, 0.82%)std::panicking::panic_count::count_is_zero (1 samples, 0.82%)core::sync::atomic::AtomicUsize::load (1 samples, 0.82%)core::sync::atomic::atomic_load (1 samples, 0.82%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_from (63 samples, 51.64%)<tftp::socket::StdSocket as tftp::socket::Socket>::recv_frompolling::Poller::wait (48 samples, 39.34%)polling::Poller::waitstd::sync::mutex::Mutex<T>::try_lock (3 samples, 2.46%)st..std::sys::unix::locks::futex_mutex::Mutex::try_lock (2 samples, 1.64%)core::sync::atomic::AtomicU32::compare_exchange (1 samples, 0.82%)core::sync::atomic::atomic_compare_exchange (1 samples, 0.82%)core::time::Duration::from_millis (1 samples, 0.82%)core::time::Duration::new (1 samples, 0.82%)core::num::<impl u64>::checked_add (1 samples, 0.82%)core::num::<impl u64>::overflowing_add (1 samples, 0.82%)heapless::vec::Vec<T,_>::truncate (1 samples, 0.82%)heapless::vec::Vec<T,_>::as_mut_ptr (1 samples, 0.82%)log::__private_api_log (1 samples, 0.82%)<env_logger::Logger as log::Log>::log (1 samples, 0.82%)std::thread::local::LocalKey<T>::try_with (1 samples, 0.82%)<env_logger::Logger as log::Log>::log::{{closure}} (1 samples, 0.82%)<env_logger::Logger as log::Log>::log::{{closure}} (1 samples, 0.82%)<alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call (1 samples, 0.82%)env_logger::fmt::Builder::build::{{closure}} (1 samples, 0.82%)env_logger::fmt::DefaultFormat::write (1 samples, 0.82%)env_logger::fmt::DefaultFormat::write_level (1 samples, 0.82%)env_logger::fmt::DefaultFormat::write_header_value (1 samples, 0.82%)log::max_level (2 samples, 1.64%)core::sync::atomic::AtomicUsize::load (2 samples, 1.64%)core::sync::atomic::atomic_load (1 samples, 0.82%)core::ops::function::FnOnce::call_once (3 samples, 2.46%)co..tftp::instant_callback::{{closure}} (2 samples, 1.64%)std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (2 samples, 1.64%)clock_gettime (2 samples, 1.64%)__vdso_clock_gettime (2 samples, 1.64%)[[vdso]] (1 samples, 0.82%)tftp::instant_callback (4 samples, 3.28%)tft..tftp::std_compat::time::Instant::from_time (4 samples, 3.28%)tft..core::time::Duration::from_micros (1 samples, 0.82%)core::time::Duration::new (1 samples, 0.82%)core::num::<impl u64>::checked_add (1 samples, 0.82%)<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (1 samples, 0.82%)arrayvec::arrayvec::ArrayVec<T,_>::as_slice (1 samples, 0.82%)arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (1 samples, 0.82%)core::slice::raw::from_raw_parts (1 samples, 0.82%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::find (3 samples, 2.46%)<c..tftp::map::Map<K,V,_>::entry::{{closure}} (1 samples, 0.82%)tftp::map::Map<K,V,_>::entry (5 samples, 4.10%)tftp..core::slice::<impl [T]>::iter (1 samples, 0.82%)core::slice::iter::Iter<T>::new (1 samples, 0.82%)core::ptr::const_ptr::<impl *const T>::is_null (1 samples, 0.82%)core::option::Option<T>::map (2 samples, 1.64%)tftp::map::OccupiedEntry<K,V,_>::get_mut::{{closure}} (1 samples, 0.82%)tftp::map::OccupiedEntry<K,V,_>::get_mut (3 samples, 2.46%)tf..core::slice::<impl [T]>::iter_mut (1 samples, 0.82%)<core::result::Result<T,E> as core::ops::try_trait::Try>::branch (2 samples, 1.64%)tftp::packet::PacketType::from_bytes (3 samples, 2.46%)tf..tftp::packet::try_from (3 samples, 2.46%)tf..core::slice::<impl [T]>::get (1 samples, 0.82%)<core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.82%)<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get (1 samples, 0.82%)core::ptr::mut_ptr::<impl *mut T>::add (1 samples, 0.82%)<I as core::iter::traits::collect::IntoIterator>::into_iter (1 samples, 0.82%)tftp::server::server::send_data_blocks (3 samples, 2.46%)tf..tftp::map::Map<K,V,_>::retain (3 samples, 2.46%)tf..arrayvec::arrayvec::ArrayVec<T,_>::retain (3 samples, 2.46%)ar..arrayvec::arrayvec::ArrayVec<T,_>::retain::process_one (3 samples, 2.46%)ar..tftp::map::Map<K,V,_>::retain::{{closure}} (2 samples, 1.64%)tftp::server::server::send_data_blocks::{{closure}} (2 samples, 1.64%)core::iter::range::<impl core::iter::traits::iterator::Iterator for core::ops::range::Range<A>>::next (1 samples, 0.82%)<core::ops::range::Range<T> as core::iter::range::RangeIteratorImpl>::spec_next (1 samples, 0.82%)core::cmp::impls::<impl core::cmp::PartialOrd for i32>::lt (1 samples, 0.82%)tftp::map::Map<K,V,_>::get (1 samples, 0.82%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::find (1 samples, 0.82%)tftp::map::Map<K,V,_>::len (3 samples, 2.46%)tf..arrayvec::arrayvec::ArrayVec<T,_>::len (2 samples, 1.64%)<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::position (1 samples, 0.82%)core::ptr::const_ptr::<impl *const T>::sub_ptr (1 samples, 0.82%)core::option::Option<T>::and_then (1 samples, 0.82%)tftp::map::Map<K,V,_>::remove (5 samples, 4.10%)tftp..tftp::map::Map<K,V,_>::iter (3 samples, 2.46%)tf..<&tftp::map::Map<K,V,_> as core::iter::traits::collect::IntoIterator>::into_iter (3 samples, 2.46%)<&..<arrayvec::arrayvec::ArrayVec<T,_> as core::ops::deref::Deref>::deref (3 samples, 2.46%)<a..arrayvec::arrayvec::ArrayVec<T,_>::as_slice (3 samples, 2.46%)ar..arrayvec::arrayvec_impl::ArrayVecImpl::as_slice (3 samples, 2.46%)ar..core::slice::raw::from_raw_parts (1 samples, 0.82%)tftp::server::server::write_block (11 samples, 9.02%)tftp::server:..<tftp::storage::FileWriter<T> as tftp::storage::BlockWriter>::write_block (10 samples, 8.20%)<tftp::stor..tftp::storage::BlockMapper::index (1 samples, 0.82%)core::ops::function::FnOnce::call_once (3 samples, 2.46%)co..tftp::instant_callback::{{closure}} (3 samples, 2.46%)tf..std::sys::unix::time::inner::<impl std::sys::unix::time::Timespec>::now (2 samples, 1.64%)clock_gettime (2 samples, 1.64%)__vdso_clock_gettime (2 samples, 1.64%)[[vdso]] (1 samples, 0.82%)[unknown] (114 samples, 93.44%)[unknown]tftp::server::server::server (111 samples, 90.98%)tftp::server::server::servertftp::std_compat::time::Instant::elapsed (4 samples, 3.28%)tft..core::time::Duration::from_micros (1 samples, 0.82%)core::time::Duration::new (1 samples, 0.82%)all (122 samples, 100%)tftp (122 samples, 100.00%)tftp_start (1 samples, 0.82%)__libc_start_main (1 samples, 0.82%)[libc.so.6] (1 samples, 0.82%)main (1 samples, 0.82%)std::rt::lang_start (1 samples, 0.82%)std::rt::lang_start_internal (1 samples, 0.82%)std::panic::catch_unwind (1 samples, 0.82%)std::panicking::try (1 samples, 0.82%)std::panicking::try::do_call (1 samples, 0.82%)std::rt::lang_start_internal::{{closure}} (1 samples, 0.82%)std::rt::init (1 samples, 0.82%)alloc::ffi::c_str::CString::new (1 samples, 0.82%)<&str as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl (1 samples, 0.82%)alloc::ffi::c_str::CString::new::spec_new_impl_bytes (1 samples, 0.82%)alloc::ffi::c_str::CString::_from_vec_unchecked (1 samples, 0.82%)alloc::vec::Vec<T,A>::push (1 samples, 0.82%) \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..e9e0852 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +imports_granularity="Crate" +group_imports="StdExternalCrate" \ No newline at end of file diff --git a/src/client/client.rs b/src/client/client.rs new file mode 100644 index 0000000..6025bbf --- /dev/null +++ b/src/client/client.rs @@ -0,0 +1,753 @@ +use core::{ + cmp::{max, min}, + time::Duration, +}; + +use log::{debug, error, info, warn}; +use rand::{CryptoRng, RngCore}; + +use super::extensions::{create_extensions, parse_extensions, validate_extensions}; +use crate::{ + config::{ + print_options, ConnectionOptions, DATA_PACKET_HEADER_SIZE, DEFAULT_DATA_BLOCK_SIZE, + ENCRYPTION_TAG_SIZE, MIN_BUFFER_SIZE, + }, + encryption::{ + encode_public_key, EncryptionKeys, EncryptionLevel, InitialKeys, PrivateKey, PublicKey, + }, + error::{BoxedResult, DefaultBoxedResult, EncryptionError, PacketError, StorageError}, + flow_control::RateControl, + key_management::{create_finalized_keys, create_initial_keys}, + packet::{ + AckPacket, ByteConverter, DataPacket, ErrorCode, ErrorPacket, Mode, Packet, + PacketExtensions, PacketType, RequestPacket, + }, + socket::Socket, + std_compat::{ + io::{ErrorKind, Read, Seek, Write}, + net::SocketAddr, + time::Instant, + }, + storage::{BlockReader, BlockWriter, FileReader, FileWriter}, + string::format_str, + time::InstantCallback, + types::{DataBuffer, DefaultString, FilePath}, +}; + +#[derive(Clone)] +pub struct ClientConfig { + pub listen: DefaultString, + pub endpoint: SocketAddr, + pub max_blocks_in_memory: u16, + pub request_timeout: Duration, + pub max_file_size: u64, + pub private_key: Option, + pub remote_public_key: Option, + pub allow_server_port_change: bool, +} + +pub fn send_file( + config: ClientConfig, + local_file_path: FilePath, + remote_file_path: FilePath, + mut options: ConnectionOptions, + create_reader: CreateReader, + socket: Sock, + instant: InstantCallback, + rng: Rng, +) -> BoxedResult<(usize, Option)> +where + R: Read + Seek, + Sock: Socket, + Rng: CryptoRng + RngCore + Copy, + CreateReader: Fn(&FilePath) -> BoxedResult<(Option, R)>, +{ + if let Ok(s) = socket.local_addr() { + info!("Listening on {} connecting to {}", s, config.endpoint); + } + debug!( + "Preparing to send {} as {}", + local_file_path, remote_file_path + ); + + #[cfg(feature = "encryption")] + let (socket, initial_keys) = create_initial_socket(socket, &config, &mut options, rng)?; + + let mut max_buffer_size = max( + options.block_size + DATA_PACKET_HEADER_SIZE as u16, + MIN_BUFFER_SIZE, + ); + + let (file_size, reader) = create_reader(&local_file_path)?; + if file_size > Some(0) { + options.file_size = file_size; + } + + #[allow(unused_must_use)] + let mut buffer = { + let mut d = DataBuffer::new(); + d.resize(max_buffer_size as usize, 0); + d + }; + + print_options("Client initial", &options); + + let (_, acknowledge, mut options, endpoint) = query_server( + &socket, + &mut buffer, + PacketType::Write, + remote_file_path, + options, + instant, + &config, + )?; + + #[cfg(feature = "encryption")] + let (socket, options) = configure_socket(socket, initial_keys, options); + + print_options("Client using", &options); + + if acknowledge { + let packet = Packet::Ack(AckPacket { block: 0 }); + socket.send_to(&mut packet.to_bytes(), endpoint)?; + } + + let mut block_reader = FileReader::from_reader( + reader, + config.max_blocks_in_memory, + options.block_size, + options.retry_packet_after_timeout, + instant, + options.window_size, + ); + + let mut timeout = instant(); + let mut total_unconfirmed = 0; + let mut total_confirmed = 0; + + let mut rate_control = RateControl::new(instant); + let mut stats_print = instant(); + let mut stats_calculate = instant(); + let mut no_work: u8 = 0; + let mut packets_to_send = u32::MAX; + let packet_send_window: u32 = 200; + + loop { + if stats_calculate.elapsed().as_millis() > packet_send_window as u128 { + rate_control.calculate_transmit_rate( + options.block_size, + options.window_size, + options.retry_packet_after_timeout.as_secs_f64(), + ); + stats_calculate = instant(); + packets_to_send = u32::MAX; + // rate_control.packets_to_send(packet_send_window, options.block_size as u32); + rate_control.print_info(); + } + if stats_print.elapsed().as_secs() > 2 { + rate_control.print_info(); + stats_print = instant(); + } + + if packets_to_send > 0 { + if let Some(block) = block_reader.next()? { + let data_length = block.data.len(); + + debug!("Send data block {} data size {}", block.block, data_length); + if block.expect_ack { + rate_control.start_rtt(block.block); + } + if block.retry > 0 { + rate_control.increment_errors(); + } + + let data_packet = Packet::Data(DataPacket { + block: block.block, + data: &block.data, + }); + match socket.send_to(&mut data_packet.to_bytes(), endpoint) { + Ok(n) => { + no_work = 1; + rate_control.data_sent(data_length); + total_unconfirmed += data_length; + packets_to_send -= 1; + debug!( + "Sent packet size {} total data size {}", + n, total_unconfirmed + ); + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + no_work = no_work.wrapping_add(1); + } + Err(e) => { + return Err(e.into()); + } + }; + } else { + no_work = no_work.wrapping_add(1); + } + } else { + no_work = no_work.wrapping_add(1); + } + + #[cfg(feature = "alloc")] + buffer.resize(max_buffer_size as usize, 0); + // TODO heapless vector resizing is super slow + #[cfg(not(feature = "alloc"))] + unsafe { + buffer.set_len(max_buffer_size as usize) + }; + + let wait_for = if no_work > 2 { + Duration::from_millis(no_work as u64).into() + } else { + None + }; + let length = match socket.recv_from(&mut buffer, wait_for) { + Ok((n, s)) => { + if s != endpoint { + continue; + } + no_work = 1; + n + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + let elapsed = timeout.elapsed(); + if elapsed > config.request_timeout { + if let Ok(s) = socket.local_addr() { + debug!("Send timeout for {}", s); + } + return Err(PacketError::Timeout(elapsed).into()); + } + no_work = no_work.wrapping_add(1); + + continue; + } + Err(e) => { + return Err(e.into()); + } + }; + buffer.truncate(length); + let data = &buffer[..length]; + + if !matches!( + PacketType::from_bytes(data), + Ok(PacketType::Ack | PacketType::Error) + ) { + debug!("Incorrect packet type received {:x?}", data); + continue; + } + match Packet::from_bytes(data) { + Ok(Packet::Ack(p)) => { + debug!("Acknowledge received {}", p.block); + timeout = instant(); + let data_length = block_reader.free_block(p.block); + + rate_control.data_received(data_length); + rate_control.end_rtt(p.block); + + total_confirmed += data_length; + + if block_reader.is_finished() { + info!("Client finished sending"); + return Ok((total_confirmed, options.remote_public_key())); + } + } + Ok(Packet::Error(p)) => { + return Err(PacketError::RemoteError(p.message).into()); + } + _ => { + debug!("Incorrect packet received {:x?}", data); + continue; + } + }; + } +} + +pub fn receive_file( + config: ClientConfig, + local_file_path: FilePath, + remote_file_path: FilePath, + mut options: ConnectionOptions, + create_writer: CreateWriter, + mut socket: Sock, + instant: InstantCallback, + rng: Rng, +) -> BoxedResult<(usize, Option)> +where + W: Write + Seek, + Rng: CryptoRng + RngCore + Copy, + Sock: Socket, + CreateWriter: Fn(&FilePath) -> BoxedResult, +{ + let mut max_buffer_size = max( + options.block_size + DATA_PACKET_HEADER_SIZE as u16, + MIN_BUFFER_SIZE, + ); + if let Ok(s) = socket.local_addr() { + info!("Listening on {} connecting to {}", s, config.endpoint); + } + debug!( + "Preparing to receive {} as {} max buffer {}", + remote_file_path, local_file_path, max_buffer_size + ); + + #[cfg(feature = "encryption")] + let (socket, initial_keys) = create_initial_socket(socket, &config, &mut options, rng)?; + + #[allow(unused_must_use)] + let mut buffer = { + let mut d = DataBuffer::new(); + d.resize(max_buffer_size as usize, 0); + d + }; + + print_options("Client initial", &options); + + let (mut received_length, acknowledge, mut options, endpoint) = query_server( + &socket, + &mut buffer, + PacketType::Read, + remote_file_path, + options, + instant, + &config, + )?; + + #[cfg(feature = "encryption")] + let (socket, options) = configure_socket(socket, initial_keys, options); + + let writer = create_writer(&local_file_path)?; + let mut block_writer = FileWriter::from_writer( + writer, + options.block_size, + config.max_blocks_in_memory, + options.window_size, + ); + + // server sent data packet so no encryption + if let Some(packet_length) = received_length.take() { + if let Ok(Packet::Data(p)) = Packet::from_bytes(&buffer[..packet_length]) { + handle_file_size(&socket, endpoint, packet_length, config.max_file_size)?; + write_block( + &socket, + endpoint, + &mut block_writer, + p.block, + p.data, + &options, + )?; + + if packet_length != options.block_size as usize { + info!("Client finished receiving"); + return Ok((packet_length, None)); + } + } + } + + print_options("Client using", &options); + + if let Some(file_size) = options.file_size { + handle_file_size(&socket, endpoint, file_size as usize, config.max_file_size)?; + } + + if acknowledge { + let packet = Packet::Ack(AckPacket { block: 0 }); + socket.send_to(&mut packet.to_bytes(), endpoint)?; + } + + let mut timeout = instant(); + let mut total = 0; + let mut no_work: u8 = 0; + + loop { + #[cfg(feature = "alloc")] + buffer.resize(max_buffer_size as usize, 0); + // TODO heapless vector resizing is super slow + #[cfg(not(feature = "alloc"))] + unsafe { + buffer.set_len(max_buffer_size as usize) + }; + + let wait_for = if no_work > 1 { + Duration::from_millis(no_work as u64).into() + } else { + None + }; + let length = match socket.recv_from(&mut buffer, wait_for) { + Ok((n, s)) => { + if s != endpoint { + continue; + } + debug!("Received packet size {}", n); + no_work = 1; + n + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + let elapsed = timeout.elapsed(); + if elapsed > config.request_timeout { + if let Ok(s) = socket.local_addr() { + debug!("Receive timeout for {}", s); + } + return Err(PacketError::Timeout(elapsed).into()); + } + no_work = no_work.wrapping_add(1); + continue; + } + Err(e) => { + return Err(e.into()); + } + }; + buffer.truncate(length); + + if !matches!( + PacketType::from_bytes(&buffer), + Ok(PacketType::Data | PacketType::Error) + ) { + debug!("Incorrect packet received {:x?}", &buffer); + continue; + } + + match Packet::from_bytes(&buffer) { + Ok(Packet::Data(p)) => { + match write_block( + &socket, + endpoint, + &mut block_writer, + p.block, + p.data, + &options, + ) { + Ok(n) => { + if n > 0 { + timeout = instant(); + no_work = 1; + } else { + no_work = no_work.wrapping_add(1); + } + total += n; + } + Err(e) => return Err(e), + } + // this would write more than expected but only by a block size maximum + handle_file_size(&socket, endpoint, total, config.max_file_size)?; + + if block_writer.is_finished_below(options.block_size) { + info!("Client finished receiving"); + return Ok((total, options.remote_public_key())); + } + } + Ok(Packet::Error(p)) => { + return Err(PacketError::RemoteError(p.message).into()); + } + _ => { + debug!("Incorrect packet received {:x?}", &buffer); + continue; + } + }; + } +} + +#[cfg(feature = "encryption")] +fn create_initial_socket( + socket: impl Socket, + config: &ClientConfig, + mut options: &mut ConnectionOptions, + rng: impl CryptoRng + RngCore + Copy, +) -> BoxedResult<( + crate::socket::EncryptionBoundSocket, + Option, +)> { + if options.encryption_level == EncryptionLevel::None { + return Ok((crate::socket::EncryptionBoundSocket::wrap(socket), None)); + } + + if let Some(p) = config.remote_public_key { + let keys = create_finalized_keys(&config.private_key, &p, None, rng); + options.encryption_keys = Some(EncryptionKeys::LocalToRemote(keys.public, p)); + if options.encryption_level == EncryptionLevel::Protocol { + options.encryption_level = EncryptionLevel::Full; + } + info!("Client public key {}", encode_public_key(&keys.public)?); + let socket = crate::socket::EncryptionBoundSocket::new( + socket, + Some(keys.encryptor), + keys.public, + options.encryption_level, + ); + return Ok((socket, None)); + } + let initial_keys = create_initial_keys(&config.private_key, rng); + info!( + "Client public key {}", + encode_public_key(&initial_keys.public)? + ); + options.encryption_keys = Some(EncryptionKeys::ClientKey(initial_keys.public)); + Ok(( + crate::socket::EncryptionBoundSocket::wrap(socket), + initial_keys.into(), + )) +} + +#[cfg(feature = "encryption")] +fn configure_socket( + mut socket: crate::socket::EncryptionBoundSocket, + initial_keys: Option, + mut options: ConnectionOptions, +) -> (impl Socket, ConnectionOptions) { + let (socket, mut options) = match ( + options.encryption_level, + initial_keys, + options.encryption_keys, + ) { + ( + EncryptionLevel::Protocol | EncryptionLevel::Data, + Some(keys), + Some(EncryptionKeys::ServerKey(p, n)), + ) => { + let final_keys = keys.finalize(&p, n); + options.encryption_keys = Some(EncryptionKeys::LocalToRemote(final_keys.public, p)); + socket.encryptor = Some(final_keys.encryptor); + socket.public_key = final_keys.public.into(); + socket.encryption_level = options.encryption_level; + (socket, options) + } + ( + EncryptionLevel::Protocol | EncryptionLevel::Data, + None, + Some(EncryptionKeys::ServerKey(p, n)), + ) => { + if socket.public_key.is_some() { + options.encryption_keys = + Some(EncryptionKeys::LocalToRemote(socket.public_key.unwrap(), p)); + } else { + options.encryption_keys = None; + } + if let Some(mut encryptor) = socket.encryptor { + encryptor.nonce = n; + socket.encryptor = encryptor.into(); + } + socket.encryption_level = options.encryption_level; + (socket, options) + } + (_, _, keys) => { + options.encryption_keys = keys; + (socket, options) + } + }; + + if socket.encryptor.is_some() + && matches!( + socket.encryption_level, + EncryptionLevel::Data | EncryptionLevel::Protocol | EncryptionLevel::Full + ) + { + options.block_size -= ENCRYPTION_TAG_SIZE as u16; + } + (socket, options) +} + +fn query_server( + socket: &impl Socket, + buffer: &mut DataBuffer, + packet_type: PacketType, + file_path: FilePath, + options: ConnectionOptions, + instant: InstantCallback, + config: &ClientConfig, +) -> BoxedResult<(Option, bool, ConnectionOptions, SocketAddr)> { + let mut extensions = create_extensions(&options); + let mut used_extensions = extensions.clone(); + let mut initial = true; + + let request_timeout = config.request_timeout; + let endpoint = config.endpoint; + + loop { + let request_packet = RequestPacket { + file_name: file_path.clone(), + mode: Mode::Octet, + extensions, + }; + let packet = match packet_type { + PacketType::Read => Packet::Read(request_packet), + PacketType::Write => Packet::Write(request_packet), + _ => panic!("Invalid packet type provided"), + }; + + let (length, endpoint) = wait_for_initial_packet( + socket, + config.endpoint, + packet, + buffer, + request_timeout, + instant, + )?; + if config.endpoint != endpoint { + if !config.allow_server_port_change { + error!("Server is using new port, however configuration does not allow it"); + return Err(PacketError::Invalid.into()); + } else { + debug!("Using new endpoint {}", endpoint); + } + } + + let data = &mut buffer[..length]; + match (packet_type, Packet::from_bytes(data)) { + (_, Ok(Packet::OptionalAck(p))) => { + if let Err(e) = validate_extensions(&p.extensions, &used_extensions) { + let message = e.message.clone(); + socket.send_to(&mut e.to_bytes(), endpoint)?; + return Err(PacketError::RemoteError(message).into()); + } + return Ok(( + None, + true, + parse_extensions(p.extensions, options)?, + endpoint, + )); + } + (PacketType::Write, Ok(Packet::Ack(_))) => { + // server disregards extensions + return Ok(( + None, + false, + options.with_block_size(DEFAULT_DATA_BLOCK_SIZE), + endpoint, + )); + } + (PacketType::Read, Ok(Packet::Data(_))) => { + // server disregards extensions + return Ok(( + Some(length), + false, + options.with_block_size(DEFAULT_DATA_BLOCK_SIZE), + endpoint, + )); + } + (_, Ok(Packet::Error(p))) => { + // retry in case server does not support extensions + if initial && options.encryption_level == EncryptionLevel::None { + debug!("Received error {} retrying without extensions", p.message); + extensions = PacketExtensions::new(); + used_extensions = Default::default(); + initial = false; + continue; + } + return Err(PacketError::RemoteError(p.message).into()); + } + _ => { + debug!("Incorrect packet received {:x?}", data); + return Err(PacketError::Invalid.into()); + } + } + } +} + +fn handle_file_size( + socket: &impl Socket, + endpoint: SocketAddr, + data_length: usize, + max_file_size: u64, +) -> DefaultBoxedResult { + if data_length > max_file_size as usize { + let message = format_str!( + DefaultString, + "Invalid file size received {} expected {}", + data_length, + max_file_size + ); + send_error(socket, endpoint, ErrorCode::DiskFull, message)?; + return Err(PacketError::Invalid.into()); + } + Ok(()) +} + +fn send_error( + socket: &impl Socket, + endpoint: SocketAddr, + code: ErrorCode, + message: DefaultString, +) -> DefaultBoxedResult { + error!("{}", message); + let packet = Packet::Error(ErrorPacket { code, message }); + socket.send_to(&mut packet.to_bytes(), endpoint)?; + Ok(()) +} + +fn write_block( + socket: &impl Socket, + endpoint: SocketAddr, + block_writer: &mut impl BlockWriter, + mut block: u16, + data: &[u8], + options: &ConnectionOptions, +) -> BoxedResult { + let (length, last_in_window) = match block_writer.write_block(block, data) { + Ok((n, l)) => (n, l), + Err(StorageError::ExpectedBlock((expected, current))) => { + debug!("Received unexpected block {} expecting {}", block, expected); + block = current; + (0, true) + } + Err(StorageError::AlreadyWriten) => { + debug!( + "Received block that was written before. Ignoring block {}", + block + ); + (0, true) + } + Err(StorageError::CapacityReached) => { + debug!( + "Capacity reached waiting for previous blocks. Ignoring block {}", + block + ); + return Ok(0); + } + Err(e) => return Err(e.into()), + }; + + if options.window_size <= 1 + || last_in_window + || block_writer.is_finished_below(options.block_size) + { + debug!("Ack send {}", block); + let packet = Packet::Ack(AckPacket { block }); + socket.send_to(&mut packet.to_bytes(), endpoint)?; + } + Ok(length) +} + +fn wait_for_initial_packet( + socket: &impl Socket, + endpoint: SocketAddr, + packet: Packet, + buffer: &mut DataBuffer, + request_timeout: Duration, + instant: InstantCallback, +) -> BoxedResult<(usize, SocketAddr)> { + let timeout = instant(); + loop { + socket.send_to(&mut packet.clone().to_bytes(), endpoint)?; + debug!("Initial packet elapsed {}", timeout.elapsed().as_secs_f32()); + + match socket.recv_from(buffer, Duration::from_millis(200).into()) { + Ok((n, s)) => { + if s.ip() == endpoint.ip() { + return Ok((n, s)); + } + continue; + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + let elapsed = timeout.elapsed(); + if elapsed > request_timeout { + return Err(PacketError::Timeout(elapsed).into()); + } + continue; + } + Err(e) => { + return Err(e.into()); + } + } + } +} diff --git a/src/client/extensions.rs b/src/client/extensions.rs new file mode 100644 index 0000000..5199067 --- /dev/null +++ b/src/client/extensions.rs @@ -0,0 +1,208 @@ +use core::time::Duration; + +use log::{debug, error}; + +use crate::{ + config::{ + ConnectionOptions, DEFAULT_DATA_BLOCK_SIZE, ENCRYPTION_TAG_SIZE, EXTENSION_BLOCK_SIZE_MIN, + EXTENSION_TIMEOUT_SIZE_MAX, EXTENSION_TIMEOUT_SIZE_MIN, EXTENSION_WINDOW_SIZE_MIN, + RETRY_PACKET_TIMEOUT, + }, + encryption::*, + error::ExtensionError, + packet::{ErrorCode, ErrorPacket, Extension, PacketExtensions}, + string::format_str, + types::DefaultString, +}; + +pub fn validate_extensions( + extensions: &PacketExtensions, + used_extensions: &PacketExtensions, +) -> Result<(), ErrorPacket> { + #[allow(unused_must_use)] + let remaining = extensions + .iter() + .filter(|(e, _)| !used_extensions.contains_key(e)) + .fold(DefaultString::new(), |mut s, (k, _)| { + s.push_str(k.as_str()); + s.push(','); + s + }); + let names = remaining.as_str().trim_end_matches(','); + if !names.is_empty() { + let message = format_str!( + DefaultString, + "Server sent options {} not initialized by client", + names + ); + return Err(ErrorPacket::new(ErrorCode::IllegalOperation, message)); + } + Ok(()) +} + +pub fn create_extensions(options: &ConnectionOptions) -> PacketExtensions { + let mut extensions = PacketExtensions::new(); + if options.block_size != DEFAULT_DATA_BLOCK_SIZE { + extensions.insert( + Extension::BlockSize, + format_str!(ExtensionValue, "{}", options.block_size as u64), + ); + } + + if options.retry_packet_after_timeout != RETRY_PACKET_TIMEOUT { + extensions.insert( + Extension::Timeout, + format_str!( + ExtensionValue, + "{}", + options.retry_packet_after_timeout.as_secs() + ), + ); + } + + if let Some(file_size) = options.file_size { + extensions.insert( + Extension::TransferSize, + format_str!(ExtensionValue, "{}", file_size), + ); + } + + if options.window_size != EXTENSION_WINDOW_SIZE_MIN { + extensions.insert( + Extension::WindowSize, + format_str!(ExtensionValue, "{}", options.window_size), + ); + } + + #[cfg(feature = "encryption")] + if options.encryption_level != EncryptionLevel::None { + match (&options.encryption_keys, options.encryption_level) { + (Some(EncryptionKeys::ClientKey(s)), l) => { + let value = encode_public_key(&s).expect("invalid key"); + extensions.insert(Extension::PublicKey, value); + extensions.insert(Extension::Nonce, "0".parse().expect("convert to string")); + extensions.insert( + Extension::EncryptionLevel, + format_str!(ExtensionValue, "{}", l), + ); + } + // protocol contains encrypted data already + (Some(EncryptionKeys::LocalToRemote(local, _)), l) + if matches!( + l, + EncryptionLevel::Data + | EncryptionLevel::OptionalData + | EncryptionLevel::OptionalProtocol + ) => + { + let value = encode_public_key(&local).expect("invalid key"); + extensions.insert(Extension::PublicKey, value); + extensions.insert(Extension::Nonce, "0".parse().expect("convert to string")); + extensions.insert( + Extension::EncryptionLevel, + format_str!(ExtensionValue, "{}", l), + ); + } + _ => (), + } + } + + debug!("Client extensions {:?}", extensions); + extensions +} + +pub fn parse_extensions( + mut extensions: PacketExtensions, + mut options: ConnectionOptions, +) -> Result { + if let Some(block_size) = extensions.get(&Extension::BlockSize) { + let server_block_size: u16 = block_size.parse().unwrap_or(0); + if (EXTENSION_BLOCK_SIZE_MIN..=options.block_size).contains(&server_block_size) { + options.block_size = server_block_size; + } else { + return Err(ExtensionError::InvalidExtension(Extension::BlockSize)); + } + } else { + options.block_size = DEFAULT_DATA_BLOCK_SIZE; + } + + if let Some(window_size) = extensions.get(&Extension::WindowSize) { + let server_window_size: u16 = window_size.parse().unwrap_or(0); + if (EXTENSION_WINDOW_SIZE_MIN..=options.window_size).contains(&server_window_size) { + options.window_size = server_window_size; + } else { + return Err(ExtensionError::InvalidExtension(Extension::WindowSize)); + } + } else { + options.window_size = EXTENSION_WINDOW_SIZE_MIN; + } + + if let Some(timeout) = extensions.get(&Extension::Timeout) { + let server_retry_seconds: u8 = timeout.parse().unwrap_or(0); + if (EXTENSION_TIMEOUT_SIZE_MIN..=EXTENSION_TIMEOUT_SIZE_MAX).contains(&server_retry_seconds) + { + options.retry_packet_after_timeout = Duration::from_secs(server_retry_seconds as u64); + } else { + return Err(ExtensionError::InvalidExtension(Extension::Timeout)); + } + } else { + options.retry_packet_after_timeout = RETRY_PACKET_TIMEOUT; + } + + if let Some(tsize) = extensions.get(&Extension::TransferSize) { + let server_file_size: u64 = tsize.parse().unwrap_or(0); + if options.file_size.is_none() { + options.file_size = Some(server_file_size); + } else if options.file_size > Some(0) && options.file_size != Some(server_file_size) { + return Err(ExtensionError::InvalidExtension(Extension::TransferSize)); + } + } + + #[cfg(feature = "encryption")] + if options.encryption_level != EncryptionLevel::Full { + let _expected_encryption_level = options.encryption_level; + if let (Some(pkey), Some(nonce), Some(Ok(level))) = ( + extensions.get(&Extension::PublicKey), + extensions.get(&Extension::Nonce), + extensions + .get(&Extension::EncryptionLevel) + .map(|s| s.parse()), + ) { + match &options.encryption_keys { + Some(EncryptionKeys::ClientKey(_)) => { + let remote_public_key = decode_public_key(pkey.as_bytes())?; + let remote_nonce = decode_nonce(nonce.as_bytes())?; + options.encryption_keys = + Some(EncryptionKeys::ServerKey(remote_public_key, remote_nonce)); + options.encryption_level = level; + } + Some(EncryptionKeys::LocalToRemote(l, r)) => { + let remote_public_key = decode_public_key(pkey.as_bytes())?; + if r.as_bytes() != remote_public_key.as_bytes() { + return Err(ExtensionError::InvalidExtension(Extension::PublicKey)); + } + let remote_nonce = decode_nonce(nonce.as_bytes())?; + options.encryption_keys = + Some(EncryptionKeys::ServerKey(remote_public_key, remote_nonce)); + options.encryption_level = level; + } + _ => return Err(ExtensionError::InvalidExtension(Extension::PublicKey)), + } + } + + if matches!( + _expected_encryption_level, + EncryptionLevel::Data | EncryptionLevel::Protocol + ) { + if !matches!( + options.encryption_level, + EncryptionLevel::Data | EncryptionLevel::Protocol + ) { + return Err(ExtensionError::ClientRequiredEncryption( + options.encryption_level, + )); + } + } + } + Ok(options) +} diff --git a/src/client/mod.rs b/src/client/mod.rs new file mode 100644 index 0000000..8e5b5f1 --- /dev/null +++ b/src/client/mod.rs @@ -0,0 +1,4 @@ +mod client; +mod extensions; + +pub use client::{receive_file, send_file, ClientConfig}; diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..59902c4 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,114 @@ +use core::{cmp::min, time::Duration}; + +use log::debug; + +use crate::{ + encryption::{EncryptionKeys, EncryptionLevel, PublicKey}, + macros::{cfg_alloc, cfg_stack_large_window, cfg_stack_many_clients}, +}; + +pub const DEFAULT_DATA_BLOCK_SIZE: u16 = 512; +pub const DATA_PACKET_HEADER_SIZE: u8 = 4; + +pub const MAX_DATA_BLOCK_SIZE: u16 = 1416; + +/// maximum size of the packet buffer +pub const MAX_BUFFER_SIZE: u16 = MAX_DATA_BLOCK_SIZE + DATA_PACKET_HEADER_SIZE as u16; +pub const MIN_BUFFER_SIZE: u16 = DEFAULT_DATA_BLOCK_SIZE + DATA_PACKET_HEADER_SIZE as u16; + +#[cfg(feature = "encryption")] +pub const ENCRYPTION_TAG_SIZE: u8 = 16; +#[cfg(not(feature = "encryption"))] +pub const ENCRYPTION_TAG_SIZE: u8 = 0; + +cfg_alloc!( + /// how many clients server can manage at once + pub const MAX_CLIENTS: u16 = 5000; + pub const MAX_BLOCKS_WRITER: u16 = 2000; + pub const MAX_BLOCKS_READER: u16 = 1000; + pub const DEFAULT_WINDOW_SIZE: u8 = 8; +); + +cfg_stack_many_clients!( + pub const MAX_CLIENTS: u16 = 100; + pub const MAX_BLOCKS_WRITER: u16 = 4; + pub const MAX_BLOCKS_READER: u16 = 4; + pub const DEFAULT_WINDOW_SIZE: u8 = 4; +); + +cfg_stack_large_window!( + pub const MAX_CLIENTS: u16 = 3; + pub const MAX_BLOCKS_WRITER: u16 = 64; + pub const MAX_BLOCKS_READER: u16 = 64; + pub const DEFAULT_WINDOW_SIZE: u8 = 8; +); + +pub const MAX_EXTENSION_VALUE_SIZE: u8 = 45; +pub const MAX_DEFAULT_STRING_SIZE: u8 = 140; +pub const MAX_FILE_PATH_SIZE: u8 = 150; + +pub const RETRY_PACKET_TIMEOUT: Duration = Duration::from_secs(1); +pub const EXTENSION_WINDOW_SIZE_MIN: u16 = 1; +// pub const EXTENSION_WINDOW_SIZE_MAX: u16 = 65535; +pub const EXTENSION_BLOCK_SIZE_MIN: u16 = 8 + ENCRYPTION_TAG_SIZE as u16; +// pub const EXTENSION_BULK_SIZE_MAX: u16 = 65464; +pub const EXTENSION_TIMEOUT_SIZE_MIN: u8 = 1; +pub const EXTENSION_TIMEOUT_SIZE_MAX: u8 = 255; + +#[derive(Clone, Debug)] +pub struct ConnectionOptions { + pub block_size: u16, + pub retry_packet_after_timeout: Duration, + pub file_size: Option, + pub encryption_keys: Option, + pub encryption_level: EncryptionLevel, + pub window_size: u16, +} + +impl Default for ConnectionOptions { + fn default() -> Self { + Self { + block_size: DEFAULT_DATA_BLOCK_SIZE, + retry_packet_after_timeout: RETRY_PACKET_TIMEOUT, + file_size: None, + encryption_keys: None, + encryption_level: EncryptionLevel::None, + window_size: EXTENSION_WINDOW_SIZE_MIN, + } + } +} + +impl ConnectionOptions { + pub fn with_block_size(mut self, block_size: u16) -> Self { + self.block_size = block_size; + self + } + + pub fn with_file_size(mut self, file_size: u64) -> Self { + self.file_size = Some(file_size); + self + } + + pub fn remote_public_key(&self) -> Option { + match self.encryption_keys { + Some(EncryptionKeys::LocalToRemote(_, p)) => p.clone().into(), + _ => None, + } + } +} + +pub fn print_options(context: &str, options: &ConnectionOptions) { + debug!( + "{} options - block_size: {}, window size: {}, file_size: {} bytes, retry packet: {}s, encryption level: {}, encrypting: {}", + context, + options.block_size, + options.window_size, + options.file_size.unwrap_or(0), + options.retry_packet_after_timeout.as_secs(), + options.encryption_level, + matches!( + options.encryption_keys, + Some(crate::encryption::EncryptionKeys::LocalToRemote(..)) + ), + ); +} diff --git a/src/encryption.rs b/src/encryption.rs new file mode 100644 index 0000000..07b1aad --- /dev/null +++ b/src/encryption.rs @@ -0,0 +1,323 @@ +use core::{fmt::Display, mem::size_of, ops::Deref, str::FromStr}; + +use base64::{engine::GeneralPurpose, Engine}; +use chacha20poly1305::{ + aead::{Buffer, Error as AeadError, KeyInit, Result as AeadResult}, + AeadInPlace, Key, XChaCha20Poly1305, XNonce, +}; +use x25519_dalek::{EphemeralSecret, PublicKey as ExternalPublicKey, StaticSecret}; + +use crate::{ + config::{DATA_PACKET_HEADER_SIZE, MAX_EXTENSION_VALUE_SIZE}, + error::{EncodingErrorType, EncryptionError}, + packet::PacketType, + types::{DataBuffer, DefaultString, ExtensionValue, ShortString}, +}; + +pub type PrivateKey = StaticSecret; +pub type PublicKey = ExternalPublicKey; +pub type Nonce = XNonce; + +pub const ENCODED_PUBLIC_KEY_LENGTH: usize = ((4 * size_of::() / 3) + 3) & !3; +pub const ENCODED_NONCE_LENGTH: usize = ((4 * size_of::() / 3) + 3) & !3; + +const ENGINE: GeneralPurpose = base64::engine::general_purpose::STANDARD; + +pub type FinalizeKeysCallback = fn(&Option, &PublicKey) -> FinalizedKeys; + +#[derive(Debug, Clone)] +pub enum EncryptionKeys { + ClientKey(PublicKey), + ServerKey(PublicKey, Nonce), + // Local, Remote + LocalToRemote(PublicKey, PublicKey), +} + +pub enum InitialKey { + Static(PrivateKey), + Ephemeral(EphemeralSecret), +} + +pub struct InitialKeys { + pub public: PublicKey, + pub private: InitialKey, +} + +impl InitialKeys { + pub fn new(public: PublicKey, private: InitialKey) -> Self { + Self { public, private } + } + + pub fn finalize(self, remote_public_key: &PublicKey, nonce: Nonce) -> FinalizedKeys { + let key = match self.private { + InitialKey::Static(k) => k.diffie_hellman(remote_public_key), + InitialKey::Ephemeral(k) => k.diffie_hellman(remote_public_key), + }; + let key: Key = key.to_bytes().into(); + FinalizedKeys { + encryptor: Encryptor { + cipher: XChaCha20Poly1305::new(&key), + nonce, + }, + public: self.public, + } + } +} + +pub struct FinalizedKeys { + pub encryptor: Encryptor, + pub public: PublicKey, +} + +impl FinalizedKeys { + pub fn nonce(&self) -> &Nonce { + &self.encryptor.nonce + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum EncryptionLevel { + Data, + Protocol, + Full, + OptionalData, + OptionalProtocol, + None, +} + +impl FromStr for EncryptionLevel { + type Err = EncryptionError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "data" => Self::Data, + "protocol" => Self::Protocol, + "full" => Self::Full, + "optional-data" => Self::OptionalData, + "optional-protocol" => Self::OptionalProtocol, + "none" => Self::None, + _ => return Err(EncryptionError::Encrypt), + }) + } +} + +impl Display for EncryptionLevel { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + EncryptionLevel::Data => write!(f, "data"), + EncryptionLevel::Protocol => write!(f, "protocol"), + EncryptionLevel::Full => write!(f, "full"), + EncryptionLevel::OptionalData => write!(f, "optional-data"), + EncryptionLevel::OptionalProtocol => write!(f, "optional-protocol"), + EncryptionLevel::None => write!(f, "none"), + } + } +} + +pub struct Encryptor { + pub cipher: XChaCha20Poly1305, + pub nonce: Nonce, +} + +impl Encryptor { + pub fn encrypt(&self, data: &mut dyn Buffer) -> Result<(), EncryptionError> { + self.cipher + .encrypt_in_place(&self.nonce, &[], data) + .map_err(|_| EncryptionError::Decrypt) + } + + pub fn decrypt(&self, data: &mut dyn Buffer) -> Result<(), EncryptionError> { + self.cipher + .decrypt_in_place(&self.nonce, &[], data) + .map_err(|_| EncryptionError::Decrypt) + } +} + +pub fn encode_nonce(nonce: &Nonce) -> Result { + let mut public_bytes = [0; ENCODED_NONCE_LENGTH]; + ENGINE + .encode_slice(nonce.deref(), &mut public_bytes) + .map_err(|_| EncryptionError::Encode(EncodingErrorType::Nonce))?; + Ok(public_bytes.into_iter().map(|b| b as char).collect()) +} + +pub fn encode_public_key(public: &PublicKey) -> Result { + let mut public_bytes = [0; ENCODED_PUBLIC_KEY_LENGTH]; + ENGINE + .encode_slice(public.as_bytes(), &mut public_bytes) + .map_err(|_| EncryptionError::Encode(EncodingErrorType::PublicKey))?; + Ok(public_bytes.into_iter().map(|b| b as char).collect()) +} + +pub fn encode_private_key(private: &PrivateKey) -> Result { + let mut private_bytes = [0; ENCODED_PUBLIC_KEY_LENGTH]; + ENGINE + .encode_slice(private.to_bytes(), &mut private_bytes) + .map_err(|_| EncryptionError::Encode(EncodingErrorType::PrivateKey))?; + Ok(private_bytes.into_iter().map(|b| b as char).collect()) +} + +pub fn decode_private_key(data: &[u8]) -> Result { + decode(data, EncodingErrorType::PrivateKey) +} + +pub fn decode_nonce(data: &[u8]) -> Result { + decode(data, EncodingErrorType::Nonce) +} + +pub fn decode_public_key(data: &[u8]) -> Result { + decode(data, EncodingErrorType::PublicKey) +} + +pub fn overwrite_data_packet( + buff: &mut DataBuffer, + callback: impl Fn(&mut dyn Buffer) -> Result<(), EncryptionError>, +) -> Result<(), EncryptionError> { + if let (Ok(PacketType::Data), Some(data_packet)) = ( + PacketType::from_bytes(buff), + buff.get(DATA_PACKET_HEADER_SIZE as usize..), + ) { + let mut data: DataBuffer = data_packet.iter().copied().collect(); + callback(&mut data)?; + buff.truncate(DATA_PACKET_HEADER_SIZE as usize); + buff.extend(data.into_iter()); + } + Ok(()) +} + +fn decode, const CAP: usize>( + data: &[u8], + error_type: EncodingErrorType, +) -> Result { + let mut remote = [0; { MAX_EXTENSION_VALUE_SIZE as usize }]; + ENGINE + .decode_slice(data, &mut remote) + .map_err(|_| EncryptionError::Decode(error_type))?; + if remote[CAP] != 0 { + return Err(EncryptionError::Decode(error_type)); + } + let remote: [u8; CAP] = remote[..CAP] + .try_into() + .map_err(|_| EncryptionError::Decode(error_type))?; + Ok(remote.into()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::config::ENCRYPTION_TAG_SIZE; + + #[test] + fn test_encrypt_decrypt() { + let encryptor = create_encryptor(); + #[cfg(feature = "alloc")] + let mut data = [2, 32, 32, 2, 1].to_vec(); + #[cfg(not(feature = "alloc"))] + let mut data: DataBuffer = [2, 32, 32, 2, 1].into_iter().collect(); + let expected = data.clone(); + encryptor.encrypt(&mut data).unwrap(); + assert_ne!(data, expected); + assert_eq!(data.len(), expected.len() + ENCRYPTION_TAG_SIZE as usize); + encryptor.decrypt(&mut data).unwrap(); + assert_eq!(data, expected); + } + + #[test] + fn test_overwrite_data() { + let encryptor = create_encryptor(); + #[cfg(feature = "alloc")] + let mut data: alloc::vec::Vec = PacketType::Data + .to_bytes() + .into_iter() + .chain([2, 32, 32, 2, 1, 11].into_iter()) + .collect(); + #[cfg(not(feature = "alloc"))] + let mut data: DataBuffer = PacketType::Data + .to_bytes() + .into_iter() + .chain([2, 32, 32, 2, 1, 11].into_iter()) + .collect(); + let mut expected = data.clone(); + overwrite_data_packet(&mut data, |buf| encryptor.encrypt(buf)).unwrap(); + assert_ne!(data, expected); + assert_eq!(data[..4], expected[..4]); + assert_eq!(data.len(), expected.len() + ENCRYPTION_TAG_SIZE as usize); + overwrite_data_packet(&mut data, |buf| encryptor.decrypt(buf)).unwrap(); + assert_eq!(data[..4], expected[..4]); + assert_eq!(data, expected); + + data[0] = 255; + expected[0] = 255; + overwrite_data_packet(&mut data, |buf| encryptor.encrypt(buf)).unwrap(); + assert_eq!(data, expected); + } + + #[test] + fn test_encode_public_key() { + let public: PublicKey = [ + 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, + 17, 22, 29, 93, 32, 1, + ] + .into(); + let encoded = encode_public_key(&public).unwrap(); + assert_eq!(encoded.len(), ENCODED_PUBLIC_KEY_LENGTH); + let decoded = decode_public_key(encoded.as_bytes()).unwrap(); + assert_eq!(public, decoded); + } + + #[test] + fn test_decode_public_key() { + let data = [ + (true, "4vF5bMfogaX8gd4U6mlefIaZYmJlUK7zrl9Z20iQa88="), + (true, "qTuwoxbFqBB96g=="), + (false, "amigo%"), + (false, "0IYTomuQrvWzX0VG8Ak2JS7FkXCuUOd2y3ehCQxWqc+7"), + ]; + for (expected, public) in data { + let encoded = decode_public_key(public.as_bytes()); + assert_eq!(expected, encoded.is_ok(), "{}", public); + } + } + + #[test] + fn test_decode_nonce() { + let data = [ + (true, "tgcjcdnaLMP6HgCy0VxQE4HGJI+nVhPT"), + (true, "qTuwoxbFqBB96g=="), + (false, "4vF5bMfogaX8gd4U6mlefIaZYmJlUK7zrl9Z20iQa88="), + (false, "amigo%"), + ]; + for (expected, nonce) in data { + let encoded = decode_nonce(nonce.as_bytes()); + assert_eq!(expected, encoded.is_ok(), "{}", nonce); + } + } + + #[test] + fn test_encode_nonce() { + let public: Nonce = [ + 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, + ] + .into(); + let encoded = encode_nonce(&public).unwrap(); + assert_eq!(encoded.len(), ENCODED_NONCE_LENGTH); + let decoded = decode_nonce(encoded.as_bytes()).unwrap(); + assert_eq!(public, decoded); + } + + fn create_encryptor() -> Encryptor { + Encryptor { + cipher: XChaCha20Poly1305::new( + &[ + 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, + 233, 200, 17, 22, 29, 93, 32, 1, + ] + .into(), + ), + nonce: [ + 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, 233, 200, 1, 3, 4, 5, 7, 3, 3, 3, 3, 2, 99, + ] + .into(), + } + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..cd4df77 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,264 @@ +use core::{ + array::TryFromSliceError, + fmt::{Display, Formatter}, + str::Utf8Error, + time::Duration, +}; + +use crate::{ + encryption::EncryptionLevel, packet::Extension, std_compat::error::Error, types::DefaultString, +}; + +#[cfg(all(feature = "std", feature = "alloc"))] +pub type BoxedError = alloc::boxed::Box; +#[cfg(not(all(feature = "std", feature = "alloc")))] +pub type BoxedError = GeneralError; +pub type BoxedResult = Result; +pub type DefaultBoxedResult = Result<(), BoxedError>; + +#[cfg(not(all(feature = "std", feature = "alloc")))] +#[derive(Debug)] +pub enum GeneralError { + PacketError(PacketError), + FileError(FileError), + StorageError(StorageError), + EncryptionError(EncryptionError), + ExtensionError(ExtensionError), + IoError(crate::std_compat::io::Error), + FmtError(core::fmt::Error), + Infallible, +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl Display for GeneralError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + GeneralError::PacketError(s) => s.fmt(f), + GeneralError::FileError(s) => s.fmt(f), + GeneralError::StorageError(s) => s.fmt(f), + GeneralError::EncryptionError(s) => s.fmt(f), + GeneralError::ExtensionError(s) => s.fmt(f), + GeneralError::IoError(s) => s.fmt(f), + GeneralError::FmtError(s) => s.fmt(f), + GeneralError::Infallible => write!(f, "unknown error"), + } + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: PacketError) -> Self { + GeneralError::PacketError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: FileError) -> Self { + GeneralError::FileError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: StorageError) -> Self { + GeneralError::StorageError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: EncryptionError) -> Self { + GeneralError::EncryptionError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: ExtensionError) -> Self { + GeneralError::ExtensionError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: crate::std_compat::io::Error) -> Self { + GeneralError::IoError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(source: core::fmt::Error) -> Self { + GeneralError::FmtError(source) + } +} + +#[cfg(not(all(feature = "std", feature = "alloc")))] +impl From for GeneralError { + fn from(_: core::convert::Infallible) -> Self { + GeneralError::Infallible + } +} + +#[derive(Debug)] +pub enum PacketError { + Invalid, + RemoteError(DefaultString), + Timeout(Duration), + InvalidString(Utf8Error), + InvalidData(TryFromSliceError), +} + +impl Display for PacketError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + PacketError::Invalid => write!(f, "Invalid packet received"), + PacketError::RemoteError(s) => write!(f, "{s}"), + PacketError::Timeout(s) => write!(f, "Timeout occured {}", s.as_secs_f32()), + PacketError::InvalidString(s) => s.fmt(f), + PacketError::InvalidData(s) => s.fmt(f), + } + } +} + +impl Error for PacketError {} + +impl From for PacketError { + fn from(source: Utf8Error) -> Self { + PacketError::InvalidString(source) + } +} + +impl From for PacketError { + fn from(source: TryFromSliceError) -> Self { + PacketError::InvalidData(source) + } +} + +pub type PacketResult = Result; + +#[derive(Debug)] +pub enum StorageError { + CapacityReached, + File(crate::std_compat::io::Error), + AlreadyWriten, + FileTooBig, + // expected, current + ExpectedBlock((u16, u16)), +} + +impl From for StorageError { + fn from(source: crate::std_compat::io::Error) -> Self { + StorageError::File(source) + } +} + +impl Error for StorageError {} + +impl Display for StorageError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + StorageError::CapacityReached => write!(f, "Buffer capacity reached"), + StorageError::File(s) => s.fmt(f), + StorageError::AlreadyWriten => write!(f, "Block has been already written"), + StorageError::FileTooBig => write!(f, "File is too big"), + StorageError::ExpectedBlock((expected, current)) => { + write!(f, "Expecting block {} current block {}", expected, current) + } + } + } +} + +#[derive(Debug)] +pub enum FileError { + InvalidFileName, +} + +impl Error for FileError {} + +impl Display for FileError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + FileError::InvalidFileName => write!(f, "Invalid file name specified"), + } + } +} + +#[derive(Debug)] +pub enum ExtensionError { + ClientRequiredEncryption(EncryptionLevel), + ServerRequiredEncryption(EncryptionLevel), + InvalidPublicKey, + InvalidNonce, + EncryptionError(EncryptionError), + InvalidExtension(Extension), +} + +impl Error for ExtensionError {} + +impl Display for ExtensionError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + ExtensionError::ClientRequiredEncryption(l) => write!( + f, + "Server does not provide encryption however client requested {l}", + ), + ExtensionError::ServerRequiredEncryption(l) => { + write!(f, "Server requires {l} encryption",) + } + ExtensionError::InvalidPublicKey => write!(f, "Invalid public key received",), + ExtensionError::InvalidNonce => write!(f, "Invalid nonce received",), + ExtensionError::EncryptionError(s) => { + write!(f, "Invalid extension parsing error {}", s) + } + ExtensionError::InvalidExtension(s) => { + write!(f, "Invalid extension {}", s) + } + } + } +} + +impl From for ExtensionError { + fn from(source: EncryptionError) -> Self { + ExtensionError::EncryptionError(source) + } +} + +#[derive(Debug, Clone, Copy)] +pub enum EncodingErrorType { + PrivateKey, + PublicKey, + Nonce, +} + +impl Display for EncodingErrorType { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + EncodingErrorType::PrivateKey => write!(f, "private key"), + EncodingErrorType::PublicKey => write!(f, "public key"), + EncodingErrorType::Nonce => write!(f, "nonce"), + } + } +} + +#[derive(Debug)] +pub enum EncryptionError { + Encrypt, + Decrypt, + Encode(EncodingErrorType), + Decode(EncodingErrorType), +} + +impl Error for EncryptionError {} + +impl Display for EncryptionError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + EncryptionError::Encrypt => write!(f, "Failed to encrypt"), + EncryptionError::Decrypt => write!(f, "Failed to decrypt"), + EncryptionError::Encode(t) => write!(f, "Failed to encode {}", t), + EncryptionError::Decode(t) => write!(f, "Failed to decode {}", t), + } + } +} diff --git a/src/flow_control.rs b/src/flow_control.rs new file mode 100644 index 0000000..4e53269 --- /dev/null +++ b/src/flow_control.rs @@ -0,0 +1,201 @@ +use core::{ops::Div, time::Duration}; + +use log::debug; + +use crate::{std_compat::time::Instant, time::InstantCallback}; + +pub struct RateControl { + // bytes/s + avg_transmit_rate: u32, + + // for measuring rtt + current_rtt: Instant, + rtt_for_packet: u16, + rtt_estimate: f64, + // + // for packet loss rate + total_packets: u32, + error_packets: u32, + // + + // for speed estimations + start: Instant, + // bytes + total_send: u64, + // bytes + total_received: u64, + // + instant: InstantCallback, +} + +impl RateControl { + pub fn new(instant: InstantCallback) -> Self { + Self { + rtt_for_packet: 0, + rtt_estimate: 0.0, + total_send: 0, + total_received: 0, + instant, + start: instant(), + current_rtt: instant(), + error_packets: 0, + avg_transmit_rate: 0, + total_packets: 0, + } + } + + pub fn increment_errors(&mut self) { + self.error_packets += 1; + } + + pub fn start_rtt(&mut self, block: u16) { + if self.current_rtt.elapsed().as_secs() > 1 { + self.rtt_for_packet = 0; + } + if self.rtt_for_packet != 0 { + return; + } + self.rtt_for_packet = block; + self.current_rtt = (self.instant)(); + } + + pub fn end_rtt(&mut self, block: u16) { + if self.rtt_for_packet == block { + if self.rtt_estimate == 0.0 { + self.rtt_estimate = self.current_rtt.elapsed().as_secs_f64(); + } else { + self.rtt_estimate = smooth_rtt_estimate( + self.rtt_estimate, + self.current_rtt.elapsed().as_secs_f64(), + ); + } + } + self.rtt_for_packet = 0; + } + + pub fn data_sent(&mut self, size: usize) { + self.total_send += size as u64; + self.total_packets += 1; + } + + pub fn data_received(&mut self, size: usize) { + self.total_received += size as u64; + } + + pub fn calculate_transmit_rate( + &mut self, + block_size: u16, + window_size: u16, + retransmission_timeout: f64, + ) { + let loss_event_rate = self.error_packets as f64 / self.total_packets as f64; + self.avg_transmit_rate = average_transmit_rate( + self.rtt_estimate, + block_size as f64, + window_size as f64, + loss_event_rate, + retransmission_timeout, + ); + } + + pub fn print_info(&self) { + debug!( + "Expected rate: {} bytes/s Current rrt: {} Average send speed: {} bytes/s Average receive speed: {} bytes/s Total packets: {} Errors: {}", + self.avg_transmit_rate, + self.rtt_estimate, + self.average_send_speed(), + self.average_receive_speed(), + self.total_packets, + self.error_packets + ) + } + + pub fn average_send_speed(&self) -> u64 { + let passed = self.start.elapsed(); + if passed.as_secs() > 0 { + self.total_send / passed.as_secs() + } else { + 0 + } + } + + pub fn average_receive_speed(&self) -> u64 { + let passed = self.start.elapsed(); + if passed.as_secs() > 0 { + self.total_received / passed.as_secs() + } else { + 0 + } + } + + /// send_window is in milliseconds and must be less than a second + #[allow(dead_code)] + pub fn packets_to_send(&self, send_window: u32, block_size: u32) -> u32 { + packets_to_send(self.avg_transmit_rate, send_window, block_size) + } +} + +fn packets_to_send(avg_rate: u32, send_window: u32, block_size: u32) -> u32 { + if avg_rate > 0 { + let mut packets = (avg_rate / block_size / (1000 / send_window)) * 2; + if packets == 0 { + packets = 1; + } + packets + } else { + u32::MAX + } +} + +fn smooth_rtt_estimate(rtt_estimate: f64, current_rrt: f64) -> f64 { + 0.9 * rtt_estimate + (1_f64 - 0.9) * current_rrt +} + +// loss_event_rate = error_packets / total_packets; +fn average_transmit_rate( + round_trip_time: f64, + block_size: f64, + window_size: f64, + loss_event_rate: f64, + retransmission_timeout: f64, +) -> u32 { + (block_size + / (round_trip_time * f64::sqrt(2_f64 * window_size * loss_event_rate / 3_f64) + + (retransmission_timeout + * (3_f64 + * f64::sqrt(3_f64 * window_size * loss_event_rate / 8_f64) + * loss_event_rate + * (1_f64 + 32_f64 * loss_event_rate.powf(2.0)))))) as u32 +} + +#[test] +fn test_average_transmit() { + let result = average_transmit_rate(0.01, 512_f64, 1_f64, 0_f64, 1_f64); + assert_eq!(result, 4294967295); + + let result = average_transmit_rate(0.01, 512_f64, 1_f64, 0.001_f64, 1_f64); + assert_eq!(result, 1618739); + + let result = average_transmit_rate(0.01, 512_f64, 8_f64, 0.001_f64, 1_f64); + assert_eq!(result, 572310); +} + +#[test] +fn test_packets_to_send() { + assert_eq!(446, packets_to_send(572310, 200, 512)); + assert_eq!(1264, packets_to_send(1618739, 200, 512)); + // send 1677721 packets * 512 / 1024 / 1024 = 819Mb in 200ms + assert_eq!(1677721 * 2, packets_to_send(4294967295, 200, 512)); + assert_eq!(4294967295, packets_to_send(0, 200, 512)); + assert_eq!(1, packets_to_send(1, 200, 512)); + assert_eq!(1, packets_to_send(128, 200, 512)); + assert_eq!(6, packets_to_send(10000, 200, 512)); +} + +#[test] +fn test_smooth_rrt_estimate() { + assert_eq!(0.275, smooth_rtt_estimate(0.25, 0.5)); + assert_eq!(0.55, smooth_rtt_estimate(0.5, 1.0)); + assert_eq!(0.46, smooth_rtt_estimate(0.5, 0.1)); + assert_eq!(0.45, smooth_rtt_estimate(0.5, 0.0)); +} diff --git a/src/key_management.rs b/src/key_management.rs new file mode 100644 index 0000000..86e0502 --- /dev/null +++ b/src/key_management.rs @@ -0,0 +1,218 @@ +use chacha20poly1305::{AeadCore, XChaCha20Poly1305}; +use rand::{CryptoRng, RngCore}; +use x25519_dalek::EphemeralSecret; + +use crate::{ + config::MAX_EXTENSION_VALUE_SIZE, + encryption::{ + decode_private_key, decode_public_key, encode_public_key, EncryptionKeys, FinalizedKeys, + InitialKey, InitialKeys, Nonce, PrivateKey, PublicKey, + }, + error::{BoxedError, BoxedResult, EncryptionError}, + server::AuthorizedKeys, + std_compat::io::{BufRead, Write}, + types::{DefaultString, ExtensionValue}, +}; + +pub fn create_initial_keys( + private: &Option, + mut rng: impl CryptoRng + RngCore, +) -> InitialKeys { + match private { + Some(k) => InitialKeys { + public: PublicKey::from(k), + private: InitialKey::Static(k.clone()), + }, + None => { + let random_key = EphemeralSecret::new(&mut rng); + InitialKeys { + public: PublicKey::from(&random_key), + private: InitialKey::Ephemeral(random_key), + } + } + } +} + +pub fn create_finalized_keys( + private: &Option, + remote_public_key: &PublicKey, + nonce: Option, + mut rng: impl CryptoRng + RngCore + Copy, +) -> FinalizedKeys { + let initial_keys = create_initial_keys(private, rng); + initial_keys.finalize( + remote_public_key, + nonce.unwrap_or_else(|| XChaCha20Poly1305::generate_nonce(rng)), + ) +} + +#[allow(unused_must_use)] +pub fn read_authorized_keys(reader: impl BufRead) -> BoxedResult { + let mut authorized_keys = AuthorizedKeys::new(); + for line in reader.lines() { + let Ok(line) = line else { + continue; + }; + if line.starts_with('#') || line.trim().is_empty() { + continue; + } + let key = decode_public_key(line.as_bytes())?; + authorized_keys.push(key); + } + Ok::<_, BoxedError>(authorized_keys) +} + +pub fn get_from_known_hosts( + reader: impl BufRead, + endpoint: &str, +) -> BoxedResult> { + for line in reader.lines() { + let Ok(line) = line else { + continue; + }; + if line.starts_with('#') || line.trim().is_empty() { + continue; + } + match line.split_once(' ') { + Some((remote_endpoint, encoded_key)) if remote_endpoint == endpoint => { + return Ok(decode_public_key(encoded_key.as_bytes())?.into()) + } + _ => continue, + } + } + Ok(None) +} + +pub fn append_to_known_hosts( + mut file: impl Write, + endpoint: &str, + public_key: &PublicKey, +) -> BoxedResult<()> { + file.write_fmt(format_args!( + "\n{} {}\n", + endpoint, + encode_public_key(&public_key)? + ))?; + Ok(()) +} + +#[cfg(test)] +mod tests { + + use vfs::{MemoryFS, VfsPath}; + + use super::*; + + #[test] + fn test_read_authorized_keys() { + let root: VfsPath = MemoryFS::new().into(); + let path = root.join("keys").unwrap(); + path + .create_file() + .unwrap() + .write_all(b"\n#Hello world\nDRKEZZt4qRdz7gp14XNyvGsFT95Fo/oFj5A+b35s8TI=\n/RtKjvdVy3lnPjPwTyXNvMsWBIFjfaG3kvOQ3VOMItg=") + .unwrap(); + let keys = read_authorized_keys(create_buff_reader(path.open_file().unwrap())).unwrap(); + assert_eq!(keys.len(), 2); + } + + #[test] + fn test_read_authorized_keys_error() { + let root: VfsPath = MemoryFS::new().into(); + let path = root.join("keys").unwrap(); + path + .create_file() + .unwrap() + .write_all(b"\nHello world\nDRKEZZt4qRdz7gp14XNyvGsFT95Fo/oFj5A+b35s8TI=\n/RtKjvdVy3lnPjPwTyXNvMsWBIFjfaG3kvOQ3VOMItg=") + .unwrap(); + let keys = read_authorized_keys(create_buff_reader(path.open_file().unwrap())); + assert!(keys.is_err()); + } + + #[test] + fn test_append_to_known_hosts() { + let root: VfsPath = MemoryFS::new().into(); + let path = root.join("keys").unwrap(); + path + .create_file() + .unwrap() + .write_all(b"\n#Hello world\nserver DRKEZZt4qRdz7gp14XNyvGsFT95Fo/oFj5A+b35s8TI=\na b /RtKjvdVy3lnPjPwTyXNvMsWBIFjfaG3kvOQ3VOMItg=") + .unwrap(); + let key = + get_from_known_hosts(create_buff_reader(path.open_file().unwrap()), "server").unwrap(); + let expected = + decode_public_key("DRKEZZt4qRdz7gp14XNyvGsFT95Fo/oFj5A+b35s8TI=".as_bytes()).unwrap(); + assert_eq!(Some(expected), key); + + let file = path.append_file().unwrap(); + #[cfg(not(feature = "std"))] + let file = StdCompatFile(file); + append_to_known_hosts(file, "new-server", &expected).unwrap(); + + let key = get_from_known_hosts(create_buff_reader(path.open_file().unwrap()), "new-server") + .unwrap(); + + assert_eq!(Some(expected), key); + + let key = get_from_known_hosts(create_buff_reader(path.open_file().unwrap()), "a"); + assert!(key.is_err()); + } + + pub fn create_buff_reader(reader: T) -> StdBufReader { + let file = std::io::BufReader::new(reader); + #[cfg(all(not(feature = "std"), feature = "encryption"))] + let file = StdBufReader(file); + file + } + + #[cfg(not(feature = "std"))] + pub struct StdCompatFile(pub std::boxed::Box); + + #[cfg(not(feature = "std"))] + impl crate::std_compat::io::Write for StdCompatFile { + fn write(&mut self, buf: &[u8]) -> crate::std_compat::io::Result { + use std::io::Write; + self.0.write(buf).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::InvalidData) + }) + } + + fn write_fmt( + &mut self, + fmt: core::fmt::Arguments<'_>, + ) -> crate::std_compat::io::Result<()> { + use std::io::Write; + self.0.write_fmt(fmt).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::InvalidData) + }) + } + + fn flush(&mut self) -> crate::std_compat::io::Result<()> { + Ok(()) + } + } + + #[cfg(all(feature = "std", feature = "encryption"))] + pub type StdBufReader = std::io::BufReader; + #[cfg(all(not(feature = "std"), feature = "encryption"))] + pub struct StdBufReader(std::io::BufReader); + #[cfg(all(not(feature = "std"), feature = "encryption"))] + impl crate::std_compat::io::BufRead for StdBufReader { + fn read_line( + &mut self, + buf: &mut crate::types::DefaultString, + ) -> crate::std_compat::io::Result { + use std::io::BufRead; + let mut s = std::string::String::new(); + let result = self.0.read_line(&mut s).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::InvalidData) + }); + let _result = buf.push_str(s.as_str()); + #[cfg(not(feature = "alloc"))] + _result.map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::InvalidData) + })?; + result + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..91f9ce4 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,156 @@ +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(unused_mut)] +#![allow(unused_imports)] +#![allow(unused_variables)] + +#[cfg(test)] +#[macro_use] +extern crate std; + +#[cfg(feature = "alloc")] +extern crate alloc; +extern crate core; + +#[cfg(feature = "alloc")] +pub mod types { + pub type DataBuffer = alloc::vec::Vec; + pub type DataBlock = alloc::vec::Vec; + pub type PacketBlock = alloc::vec::Vec; + pub type PacketExtensionNames<'a> = alloc::vec::Vec<&'a str>; + pub type DefaultString = alloc::string::String; + pub type ExtensionValue = alloc::string::String; + pub type ShortString = alloc::string::String; + pub type FilePath = alloc::string::String; +} + +#[cfg(not(feature = "alloc"))] +pub mod types { + // heapless::Vec resizing is very slow + pub type DataBuffer = heapless::Vec; + pub type PacketBlock = DataBuffer; + pub type DataBlock = heapless::Vec; + pub type PacketExtensionNames<'a> = + heapless::Vec<&'a str, { crate::packet::Extension::SIZE as usize }>; + pub type DefaultString = heapless::String<{ crate::config::MAX_DEFAULT_STRING_SIZE as usize }>; + // max possible extension value (largest public key 45 bytes) + pub type ExtensionValue = + heapless::String<{ crate::config::MAX_EXTENSION_VALUE_SIZE as usize }>; + pub type ShortString = ExtensionValue; + pub type FilePath = heapless::String<{ crate::config::MAX_FILE_PATH_SIZE as usize }>; +} + +mod string { + macro_rules! format_str { + ($stype:ident, $($t:tt)*) => {{ + use core::fmt::Write; + let mut s = crate::types::$stype::new(); + write!(&mut s, $($t)*).expect("number must fit"); + s + }}; + } + pub(crate) use format_str; +} + +pub mod time { + use crate::std_compat::time::Instant; + pub type InstantCallback = fn() -> Instant; +} + +#[cfg(feature = "alloc")] +mod map { + pub use alloc::collections::{btree_map::Entry, BTreeMap as Map}; +} + +#[cfg(feature = "std")] +pub mod std_compat { + pub mod time { + pub use std::time::Instant; + } + + pub mod io { + pub use std::io::{BufRead, Error, ErrorKind, Read, Result, Seek, SeekFrom, Write}; + } + + pub mod error { + pub use std::error::Error; + } + + pub mod net { + pub use std::net::SocketAddr; + } +} + +pub mod client; +pub mod config; +#[cfg(feature = "encryption")] +pub mod encryption; +mod macros; +#[cfg(not(feature = "encryption"))] +pub mod encryption { + pub type InitialKeys = (); + pub type PublicKey = (); + pub type Nonce = (); + pub type Encryptor = (); + pub struct FinalizedKeys { + pub encryptor: Encryptor, + } + pub type PrivateKey = (); + pub type InitialKey = (); + pub type FinalizeKeysCallback = fn((), ()) -> (); + pub fn overwrite_data_packet() {} + pub fn encode_public_key() {} + pub fn encode_nonce() {} + pub fn decode_public_key() {} + pub fn decode_private_key() {} + + #[derive(Clone, Debug)] + pub enum EncryptionKeys { + ClientKey(PublicKey), + ServerKey(PublicKey, Nonce), + LocalToRemote(PublicKey, PublicKey), + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub enum EncryptionLevel { + Data, + Protocol, + Full, + OptionalData, + OptionalProtocol, + None, + } + impl core::fmt::Display for EncryptionLevel { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + EncryptionLevel::Data => write!(f, "data"), + EncryptionLevel::Protocol => write!(f, "protocol"), + EncryptionLevel::Full => write!(f, "full"), + EncryptionLevel::OptionalData => write!(f, "optional-data"), + EncryptionLevel::OptionalProtocol => write!(f, "optional-protocol"), + EncryptionLevel::None => write!(f, "none"), + } + } + } +} +pub mod error; +#[cfg(not(feature = "alloc"))] +mod map; + +mod flow_control; +mod packet; +pub mod server; +pub mod socket; +#[cfg(not(feature = "std"))] +pub mod std_compat; +mod storage; + +#[cfg(feature = "encryption")] +pub mod key_management; +#[cfg(not(feature = "encryption"))] +pub mod key_management { + pub fn append_to_known_hosts() {} + pub fn get_from_known_hosts() {} + pub fn read_authorized_keys() {} + pub fn create_finalized_keys() {} + pub fn create_initial_keys() {} +} diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..3f62b01 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,30 @@ +macro_rules! cfg_alloc { + ($($item:item)*) => { + $( + #[cfg(feature = "alloc")] + $item + )* + } +} + +macro_rules! cfg_stack_many_clients { + ($($item:item)*) => { + $( + #[cfg(all(not(feature = "alloc"), not(feature = "stack_large_window")))] + $item + )* + } +} + +macro_rules! cfg_stack_large_window { + ($($item:item)*) => { + $( + #[cfg(feature = "stack_large_window")] + $item + )* + } +} + +pub(crate) use cfg_alloc; +pub(crate) use cfg_stack_large_window; +pub(crate) use cfg_stack_many_clients; diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..640e519 --- /dev/null +++ b/src/map.rs @@ -0,0 +1,276 @@ +use arrayvec::ArrayVec; + +/// Simple map which relies on the fact that there wont be many entries see benches +#[derive(Clone, Debug)] +pub struct Map { + array: ArrayVec<(K, V), CAP>, +} + +impl Default for Map { + fn default() -> Self { + Self { + array: Default::default(), + } + } +} + +pub enum Entry<'a, K: 'a, V: 'a, const CAP: usize> { + Occupied(OccupiedEntry<'a, K, V, CAP>), + Vacant(VacantEntry<'a, K, V, CAP>), +} + +pub struct OccupiedEntry<'a, K, V, const CAP: usize> { + key: K, + parent: &'a mut ArrayVec<(K, V), CAP>, +} + +impl<'a, K, V, const CAP: usize> OccupiedEntry<'a, K, V, CAP> +where + K: PartialEq, +{ + pub fn get(&self) -> &V { + self.parent + .iter() + .find(|(k, _)| k == &self.key) + .map(|(_, v)| v) + .expect("entry should have a value") + } + + pub fn get_mut(&mut self) -> &mut V { + self.parent + .iter_mut() + .find(|(k, _)| k == &self.key) + .map(|(_, v)| v) + .expect("entry should have a value") + } + + pub fn remove(&mut self) { + self.parent.retain(|(k, _)| k != &self.key); + } +} + +pub struct VacantEntry<'a, K, V, const CAP: usize> { + key: K, + parent: &'a mut ArrayVec<(K, V), CAP>, +} + +impl<'a, K, V, const CAP: usize> VacantEntry<'a, K, V, CAP> { + pub fn insert(self, value: V) { + self.parent.push((self.key, value)); + } +} + +impl Map { + pub fn new() -> Self { + Self { + array: ArrayVec::<(K, V), CAP>::new_const(), + } + } + + pub fn len(&self) -> usize { + self.array.len() + } + + pub fn is_empty(&self) -> bool { + self.array.is_empty() + } + + pub fn entry(&mut self, entry_key: K) -> Entry + where + K: Eq, + { + if let Some(_) = self.array.iter().find(|(k, _)| k == &entry_key) { + return Entry::Occupied(OccupiedEntry { + key: entry_key, + parent: &mut self.array, + }); + } + Entry::Vacant(VacantEntry { + key: entry_key, + parent: &mut self.array, + }) + } + + pub fn insert(&mut self, key: K, value: V) -> Option + where + K: Eq, + { + let element = self.remove(&key); + self.array.try_push((key, value)).expect("insert item"); + element + } + + pub fn contains_key(&self, key: &K) -> bool + where + K: Eq, + { + self.array + .iter() + .find(|(k, _)| k == key) + .map(|_| true) + .unwrap_or(false) + } + + pub fn get_mut(&mut self, key: &K) -> Option<&mut V> + where + K: Eq, + { + self.array + .iter_mut() + .find(|(k, _)| k == key) + .map(|(_, v)| v) + } + + pub fn get(&self, key: &K) -> Option<&V> + where + K: Eq, + { + self.array.iter().find(|(k, _)| k == key).map(|(_, v)| v) + } + + pub fn remove(&mut self, key: &K) -> Option + where + K: Eq, + { + let pos = self.iter().position(|(k, _)| k == key); + pos.and_then(|i| self.array.pop_at(i).map(|(_, v)| v)) + } + + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&mut K, &mut V) -> bool, + { + self.array.retain(|(k, v)| f(k, v)); + } + + pub fn iter(&self) -> impl Iterator { + self.into_iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator { + self.into_iter() + } +} + +impl core::ops::Index<&K> for Map +where + K: Eq, +{ + type Output = V; + + fn index(&self, key: &K) -> &Self::Output { + self.array + .iter() + .find(|(k, _)| k == key) + .map(|(_, v)| v) + .expect("value expected") + } +} + +impl IntoIterator for Map { + type Item = (K, V); + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.array.into_iter() + } +} + +impl<'a, K, V, const CAP: usize> IntoIterator for &'a Map { + type Item = &'a (K, V); + type IntoIter = <&'a ArrayVec<(K, V), CAP> as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.array.iter() + } +} + +impl<'a, K, V, const CAP: usize> IntoIterator for &'a mut Map { + type Item = &'a mut (K, V); + type IntoIter = <&'a mut ArrayVec<(K, V), CAP> as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.array.iter_mut() + } +} + +impl FromIterator<(K, V)> for Map +where + K: Eq, +{ + fn from_iter>(iter: I) -> Self { + let mut c = Map::new(); + for (k, v) in iter { + c.insert(k, v); + } + c + } +} + +impl<'a, K, V, const CAP: usize> FromIterator<&'a (K, V)> for Map<&'a K, &'a V, CAP> +where + K: Eq, +{ + fn from_iter>(iter: I) -> Self { + let mut c = Map::new(); + for (k, v) in iter { + c.insert(k, v); + } + c + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_basic_ops() { + let mut map = Map::::new(); + + assert!(map.is_empty()); + map.insert(1, 1); + map.insert(2, 2); + map.insert(3, 3); + assert!(!map.is_empty()); + assert_eq!(map.len(), 3); + + assert_eq!(map.remove(&4), None); + + assert!(map.contains_key(&3)); + assert_eq!(map.remove(&3), Some(3)); + assert!(!map.contains_key(&3)); + + assert_eq!(map.len(), 2); + assert_eq!(map.insert(1, 2), Some(1)); + assert_eq!(map.len(), 2); + + assert_eq!(map[&1], 2); + + let mut iter = map.into_iter(); + assert_eq!(iter.next(), Some((2, 2))); + assert_eq!(iter.next(), Some((1, 2))); + assert_eq!(iter.next(), None); + + let mut map: Map = [(1, 1), (2, 2), (3, 3)].into_iter().collect(); + assert_eq!(map.len(), 3); + map.retain(|k, v| *k != 2); + assert_eq!(map.len(), 2); + } + + #[test] + #[should_panic] + fn test_capacity() { + let mut map = Map::::new(); + map.insert(1, 1); + assert_eq!(map.len(), 1); + map.insert(1, 2); + assert_eq!(map.len(), 1); + map.insert(2, 2); + } + + #[test] + #[should_panic] + fn test_capacity_from_iter() { + let mut map: Map = [(1, 1), (2, 2), (3, 3)].into_iter().collect(); + } +} diff --git a/src/packet.rs b/src/packet.rs new file mode 100644 index 0000000..19d4a2a --- /dev/null +++ b/src/packet.rs @@ -0,0 +1,744 @@ +use core::{ + fmt::{Display, Formatter}, + hash::Hash, + mem::{size_of, size_of_val}, + str::{from_utf8, FromStr}, +}; + +use crate::{ + error::{PacketError, PacketResult}, + map::Map, + types::{DefaultString, ExtensionValue, FilePath, PacketBlock}, +}; + +#[cfg(feature = "alloc")] +pub type PacketExtensions = Map; +#[cfg(not(feature = "alloc"))] +pub type PacketExtensions = Map; + +pub trait ByteConverter<'a> { + fn from_bytes(bytes: &'a [u8]) -> PacketResult + where + Self: Sized; + fn to_bytes(self) -> PacketBlock; +} + +#[derive(Debug, Clone)] +pub enum Packet<'a> { + Read(RequestPacket), + Write(RequestPacket), + Data(DataPacket<'a>), + Ack(AckPacket), + Error(ErrorPacket), + OptionalAck(OptionalAck), +} + +impl<'a> Packet<'a> { + pub fn packet_type(&self) -> PacketType { + match self { + Packet::Read(_) => PacketType::Read, + Packet::Write(_) => PacketType::Write, + Packet::Ack(_) => PacketType::Ack, + Packet::Data(_) => PacketType::Data, + Packet::Error(_) => PacketType::Error, + Packet::OptionalAck(_) => PacketType::OptionalAck, + } + } +} + +impl<'a> ByteConverter<'a> for Packet<'a> { + fn from_bytes(bytes: &'a [u8]) -> PacketResult { + let opcode = PacketType::from_bytes(bytes)?; + let remaining = bytes + .get(size_of_val(&opcode)..) + .ok_or(PacketError::Invalid)?; + Ok(match opcode { + PacketType::Read => Packet::Read(RequestPacket::from_bytes(remaining)?), + PacketType::Write => Packet::Write(RequestPacket::from_bytes(remaining)?), + PacketType::Data => Packet::Data(DataPacket::from_bytes(remaining)?), + PacketType::Ack => Packet::Ack(AckPacket::from_bytes(remaining)?), + PacketType::Error => Packet::Error(ErrorPacket::from_bytes(remaining)?), + PacketType::OptionalAck => Packet::OptionalAck(OptionalAck::from_bytes(remaining)?), + _ => return Err(PacketError::Invalid), + }) + } + + fn to_bytes(self) -> PacketBlock { + match self { + Packet::Read(p) => PacketType::Read + .to_bytes() + .into_iter() + .chain(p.to_bytes().into_iter()) + .collect(), + Packet::Write(p) => PacketType::Write + .to_bytes() + .into_iter() + .chain(p.to_bytes().into_iter()) + .collect(), + Packet::Data(p) => PacketType::Data + .to_bytes() + .into_iter() + .chain(p.to_bytes().into_iter()) + .collect(), + Packet::Ack(p) => PacketType::Ack + .to_bytes() + .into_iter() + .chain(p.to_bytes().into_iter()) + .collect(), + Packet::Error(p) => PacketType::Error + .to_bytes() + .into_iter() + .chain(p.to_bytes().into_iter()) + .collect(), + Packet::OptionalAck(p) => PacketType::OptionalAck + .to_bytes() + .into_iter() + .chain(p.to_bytes().into_iter()) + .collect(), + } + } +} + +#[derive(Debug, PartialEq, Clone, Copy)] +#[repr(u16)] +pub enum PacketType { + Read = 1, + Write, + Data, + Ack, + Error, + OptionalAck, + InitialEncryption = 13432, +} + +impl PacketType { + fn from_repr(s: u16) -> PacketResult { + Ok(match s { + 1 => PacketType::Read, + 2 => PacketType::Write, + 3 => PacketType::Data, + 4 => PacketType::Ack, + 5 => PacketType::Error, + 6 => PacketType::OptionalAck, + // TODO randomize + 13432 => PacketType::InitialEncryption, + _ => return Err(PacketError::Invalid), + }) + } +} + +impl PacketType { + pub fn from_bytes(bytes: &[u8]) -> PacketResult { + Self::from_repr(try_from(bytes)?) + } + + pub fn to_bytes(self) -> [u8; size_of::()] { + (self as u16).to_be_bytes() + } +} + +impl Display for PacketType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + PacketType::Read => write!(f, "read packet"), + PacketType::Write => write!(f, "read packet"), + PacketType::Ack => write!(f, "ack packet"), + PacketType::Data => write!(f, "data packet"), + PacketType::Error => write!(f, "error packet"), + PacketType::OptionalAck => write!(f, "optional ack packet"), + _ => write!(f, "unknown packet"), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Mode { + Octet, +} + +impl Mode { + pub fn as_str(&self) -> &str { + match self { + Self::Octet => "octet", + } + } +} + +impl FromStr for Mode { + type Err = PacketError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "octet" => Self::Octet, + _ => return Err(PacketError::Invalid), + }) + } +} + +#[derive(Debug, PartialEq, Eq, Hash, Clone, Ord, PartialOrd)] +#[repr(u8)] +pub enum Extension { + // "8" and "65464" + BlockSize, + // "1" and "255" + Timeout, + // file size + TransferSize, + // client/server public key + PublicKey, + // server nonce + Nonce, + // required encryption level + EncryptionLevel, + // "1" and "65535" + WindowSize, +} + +#[cfg(not(feature = "alloc"))] +impl hash32::Hash for Extension { + fn hash(&self, state: &mut H) + where + H: hash32::Hasher, + { + let t = self.clone() as u8; + state.write(&[t]); + } +} + +impl Extension { + pub const SIZE: u8 = 7; + + pub fn as_str(&self) -> &str { + match self { + Self::BlockSize => "blksize", + Self::Timeout => "timeout", + Self::TransferSize => "tsize", + Self::PublicKey => "pkey", + Self::Nonce => "nonce", + Self::EncryptionLevel => "enclevel", + Self::WindowSize => "windowsize", + } + } +} + +impl Display for Extension { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl FromStr for Extension { + type Err = PacketError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "blksize" | "BLKSIZE" => Self::BlockSize, + "timeout" | "TIMEOUT" => Self::Timeout, + "tsize" | "TSIZE" => Self::TransferSize, + "pkey" | "PKEY" => Self::PublicKey, + "nonce" | "NONCE" => Self::Nonce, + "enclevel" | "ENCLEVEL" => Self::EncryptionLevel, + "windowsize" | "WINDOWSIZE" => Self::WindowSize, + _ => return Err(PacketError::Invalid), + }) + } +} + +#[derive(Debug, Clone)] +pub struct OptionalAck { + pub extensions: PacketExtensions, +} + +impl<'a> ByteConverter<'a> for OptionalAck { + fn from_bytes(bytes: &[u8]) -> PacketResult { + let mut rest = bytes; + let mut extensions = PacketExtensions::new(); + while extensions.len() < Extension::SIZE as usize { + let (next, name) = match rest.iter().position(|&c| c == b'\0') { + Some(n) => (rest.get(n + 1..), from_utf8(&rest[0..n])?), + _ => return Err(PacketError::Invalid), + }; + + let Some(next) = next else { + return Err(PacketError::Invalid); + }; + + let (next, value) = match next.iter().position(|&c| c == b'\0') { + Some(n) => (next.get(n + 1..), from_utf8(&next[0..n])?), + _ => return Err(PacketError::Invalid), + }; + + if let (Ok(extension), Ok(value)) = (name.parse(), value.parse()) { + extensions.insert(extension, value); + }; + + match next { + Some(r) if !r.is_empty() => rest = r, + _ => break, + }; + } + Ok(Self { extensions }) + } + + fn to_bytes(self) -> PacketBlock { + self.extensions + .into_iter() + .fold(PacketBlock::new(), |mut v, (key, value)| { + let bytes = key + .as_str() + .as_bytes() + .iter() + .copied() + .chain([0].into_iter()) + .chain(value.as_bytes().iter().copied()) + .chain([0].into_iter()); + v.extend(bytes); + v + }) + } +} + +#[derive(Debug, Clone)] +pub struct RequestPacket { + pub file_name: FilePath, + pub mode: Mode, + pub extensions: PacketExtensions, +} + +impl<'a> ByteConverter<'a> for RequestPacket { + fn from_bytes(bytes: &[u8]) -> PacketResult { + let (rest, name) = match bytes.iter().position(|&c| c == b'\0') { + Some(n) => ( + bytes.get(n + 1..).ok_or(PacketError::Invalid)?, + from_utf8(&bytes[0..n])?, + ), + _ => return Err(PacketError::Invalid), + }; + let file_name = name.parse().map_err(|_duration| PacketError::Invalid)?; + + let (rest, octet) = match rest.iter().position(|&c| c == b'\0') { + Some(n) => (rest.get(n + 1..), from_utf8(&rest[..n])?), + _ => return Err(PacketError::Invalid), + }; + let mode = octet.parse().map_err(|_duration| PacketError::Invalid)?; + + let extensions = match rest { + Some(b) if !b.is_empty() => OptionalAck::from_bytes(b)?.extensions, + _ => PacketExtensions::new(), + }; + + Ok(Self { + file_name, + mode, + extensions, + }) + } + + fn to_bytes(self) -> PacketBlock { + let name = self.file_name.as_str(); + let optional = OptionalAck { + extensions: self.extensions, + }; + name.as_bytes() + .iter() + .copied() + .chain([0].into_iter()) + .chain(self.mode.as_str().as_bytes().iter().copied()) + .chain([0].into_iter()) + .chain(optional.to_bytes().into_iter()) + .collect() + } +} + +#[derive(Debug, Clone)] +pub struct DataPacket<'a> { + pub block: u16, + pub data: &'a [u8], +} + +impl<'a> ByteConverter<'a> for DataPacket<'a> { + fn from_bytes(bytes: &'a [u8]) -> PacketResult { + let block = try_from(bytes)?; + Ok(Self { + block, + data: bytes + .get(size_of_val(&block)..) + .ok_or(PacketError::Invalid)?, + }) + } + + fn to_bytes(self) -> PacketBlock { + self.block + .to_be_bytes() + .into_iter() + .chain(self.data.iter().copied()) + .collect() + } +} + +#[derive(Debug, Clone)] +pub struct AckPacket { + pub block: u16, +} + +impl<'a> ByteConverter<'a> for AckPacket { + fn from_bytes(bytes: &[u8]) -> PacketResult { + Ok(Self { + block: try_from(bytes)?, + }) + } + + fn to_bytes(self) -> PacketBlock { + self.block.to_be_bytes().into_iter().collect() + } +} + +#[derive(Debug, PartialEq, Clone, Copy)] +#[repr(u16)] +pub enum ErrorCode { + Undefined, + FileNotFound, + AccessVioliation, + DiskFull, + IllegalOperation, + UnknownId, + FileAlreadyExists, + NotSuchUser, +} + +impl Display for ErrorCode { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + ErrorCode::Undefined => write!(f, "Undefined"), + ErrorCode::FileNotFound => write!(f, "FileNotFound"), + ErrorCode::AccessVioliation => write!(f, "AccessVioliation"), + ErrorCode::DiskFull => write!(f, "DiskFull"), + ErrorCode::IllegalOperation => write!(f, "IllegalOperation"), + ErrorCode::UnknownId => write!(f, "UnknownId"), + ErrorCode::FileAlreadyExists => write!(f, "FileAlreadyExists"), + ErrorCode::NotSuchUser => write!(f, "NotSuchUser"), + } + } +} + +impl ErrorCode { + fn from_repr(s: u16) -> Option { + match s { + 0 => ErrorCode::Undefined, + 1 => ErrorCode::FileNotFound, + 2 => ErrorCode::AccessVioliation, + 3 => ErrorCode::DiskFull, + 4 => ErrorCode::IllegalOperation, + 5 => ErrorCode::UnknownId, + 6 => ErrorCode::FileAlreadyExists, + 7 => ErrorCode::NotSuchUser, + _ => return None, + } + .into() + } +} + +#[derive(Debug, Clone)] +pub struct ErrorPacket { + pub code: ErrorCode, + pub message: DefaultString, +} + +impl ErrorPacket { + pub fn new(code: ErrorCode, message: DefaultString) -> Self { + Self { code, message } + } +} + +impl<'a> ByteConverter<'a> for ErrorPacket { + fn from_bytes(bytes: &[u8]) -> PacketResult { + let code = try_from(bytes)?; + let code = ErrorCode::from_repr(code).ok_or(PacketError::Invalid)?; + let message_bytes = bytes + .get(size_of_val(&code)..) + .ok_or(PacketError::Invalid)?; + let message = match message_bytes.iter().position(|&c| c == b'\0') { + Some(n) => from_utf8(&message_bytes[..n])?, + _ => return Err(PacketError::Invalid), + }; + Ok(Self { + code, + message: message.parse().map_err(|_| PacketError::Invalid)?, + }) + } + + fn to_bytes(self) -> PacketBlock { + (self.code as u16) + .to_be_bytes() + .into_iter() + .chain(self.message.as_bytes().iter().copied()) + .chain([0].into_iter()) + .collect() + } +} + +fn try_from(bytes: &[u8]) -> Result { + Ok(u16::from_be_bytes( + bytes + .get(..size_of::()) + .ok_or(PacketError::Invalid)? + .try_into()?, + )) +} + +#[cfg(test)] +mod tests { + use core::str::FromStr; + + use super::*; + use crate::string::format_str; + + #[test] + fn test_read() { + let data = [ + (true, b"\x00\x01foobar.txt\x00octet\x00".to_vec()), + (false, b"\x00\x01foobar.txtoctet\x00".to_vec()), + (false, b"\x00\x01foobar.txt\x00octet".to_vec()), + (false, b"\x00\x01foobar.txtoctet".to_vec()), + // extensions + (true, b"\x00\x01foobar.txt\x00octet\x00blksize\x001252\x00".to_vec()), + (true, b"\x00\x01foobar.txt\x00octet\x00blksize\x001252\x00tsize\x002000\x00timeout\x001\x00windowsize\x008\x00".to_vec()), + (false, b"\x00\x01foobar.txt\x00octet\x00blksize\x001252\x00tsize\x002000\x00timeout\x00".to_vec()), + ]; + + for (index, (expected, request)) in data.into_iter().enumerate() { + let packet = Packet::from_bytes(&request); + assert_eq!(packet.is_ok(), expected, "{index} {packet:?}"); + if expected { + assert!(matches!(packet, Ok(Packet::Read(RequestPacket { .. })))); + } + } + + assert_eq!( + Packet::Read(RequestPacket { + file_name: "foobar.txt".parse().unwrap(), + mode: Mode::Octet, + extensions: Default::default(), + }) + .to_bytes() + .as_slice(), + b"\x00\x01foobar.txt\x00octet\x00" + ); + } + + #[test] + fn test_write() { + let data = [ + (true, b"\x00\x02foobar.txt\x00octet\x00".to_vec()), + (false, b"\x00\x02foobar.txtoctet\x00".to_vec()), + (false, b"\x00\x02foobar.txt\x00octet".to_vec()), + (false, b"\x00\x02foobar.txtoctet".to_vec()), + ]; + + for (index, (expected, request)) in data.into_iter().enumerate() { + let packet = Packet::from_bytes(&request); + assert_eq!(packet.is_ok(), expected, "{index} {packet:?}"); + if expected { + assert!(matches!(packet, Ok(Packet::Write(RequestPacket { .. })))); + } + } + + assert_eq!( + Packet::Write(RequestPacket { + file_name: "foobar.txt".parse().unwrap(), + mode: Mode::Octet, + extensions: Default::default(), + }) + .to_bytes() + .as_slice(), + b"\x00\x02foobar.txt\x00octet\x00" + ); + } + + #[test] + fn test_data() { + let data = [ + (true, b"\x00\x03\x00\x01".to_vec()), + (true, b"\x00\x03\x00\x01\x33\x55".to_vec()), + (false, b"\x00\x03\x00".to_vec()), + (false, b"\x00\x03".to_vec()), + (false, b"".to_vec()), + ]; + + for (index, (expected, request)) in data.into_iter().enumerate() { + let packet = Packet::from_bytes(&request); + assert_eq!(packet.is_ok(), expected, "{index} {packet:?}"); + if expected { + assert!(matches!(packet, Ok(Packet::Data(DataPacket { .. })))); + } + } + + assert_eq!( + Packet::Data(DataPacket { + block: 1, + data: &[0x30, 0x31], + }) + .to_bytes() + .as_slice(), + b"\x00\x03\x00\x01\x30\x31" + ); + } + + #[test] + fn test_ack() { + let data = [ + (true, b"\x00\x04\x00\x01".to_vec()), + (false, b"\x00\x04\x00".to_vec()), + (false, b"\x00\x04".to_vec()), + (false, b"".to_vec()), + ]; + + for (index, (expected, request)) in data.into_iter().enumerate() { + let packet = Packet::from_bytes(&request); + assert_eq!(packet.is_ok(), expected, "{index} {packet:?}"); + if expected { + assert!(matches!(packet, Ok(Packet::Ack(AckPacket { .. })))); + } + } + + assert_eq!( + Packet::Ack(AckPacket { block: 1 }).to_bytes().as_slice(), + b"\x00\x04\x00\x01" + ); + } + + #[test] + fn test_error() { + let data = [ + (true, b"\x00\x05\x00\x01File not found\x00".to_vec()), + (cfg!(feature = "alloc"), b"\x00\x05\x00\x01File not found File not found File not found File not found File not found File not found File + not found File not found File not found File not found File not found File not found\x00".to_vec()), + (false, b"\x00\x05\x00\x09File not found\x00".to_vec()), + (false, b"\x00\x05File not found\x00".to_vec()), + (false, b"\x00\x05\x00\x01File not found".to_vec()), + ]; + + for (index, (expected, request)) in data.into_iter().enumerate() { + let packet = Packet::from_bytes(&request); + assert_eq!(packet.is_ok(), expected, "{index} {packet:?}"); + if expected { + assert!(matches!(packet, Ok(Packet::Error(ErrorPacket { .. })))); + } + } + + let packet = + ErrorPacket::from_bytes(b"\x00\x01Testing long meesage where file is not found\x00") + .unwrap(); + assert_eq!(ErrorCode::FileNotFound, packet.code); + assert_eq!( + "Testing long meesage where file is not found", + packet.message + ); + + assert_eq!( + Packet::Error(ErrorPacket { + code: ErrorCode::FileNotFound, + message: "File not found".parse().unwrap() + }) + .to_bytes() + .as_slice(), + b"\x00\x05\x00\x01File not found\x00" + ); + } + + #[test] + fn test_optional_ack() { + let data = [ + (true, b"\x00\x06blksize\x001252\x00".to_vec()), + ( + true, + b"\x00\x06blksize\x001252\x00timeout\x001252\x00tsize\x001252\x00".to_vec(), + ), + (true, b"\x00\x06blks\x001252\x00".to_vec()), + ( + true, + b"\x00\x06blksize\x001252\x00unknown\x001252\x00tsize\x001252\x00".to_vec(), + ), + ( + false, + b"\x00\x06blksize\x001252\x00unknown\x001252\x00tsize\x001252".to_vec(), + ), + ( + false, + b"\x00\x06blksize\x001252\x00unknown\x001252\x00tsize\x00".to_vec(), + ), + ]; + + for (index, (expected, request)) in data.into_iter().enumerate() { + let packet = Packet::from_bytes(&request); + assert_eq!(packet.is_ok(), expected, "{index} {packet:?}"); + if expected { + assert!(matches!( + packet, + Ok(Packet::OptionalAck(OptionalAck { .. })) + )); + } + } + + assert_eq!( + Packet::OptionalAck(OptionalAck { + extensions: [ + (Extension::Timeout, format_str!(ExtensionValue, "{}", 123)), + ( + Extension::TransferSize, + format_str!(ExtensionValue, "{}", 123) + ), + ] + .into_iter() + .collect() + }) + .to_bytes() + .as_slice(), + b"\x00\x06timeout\x00123\x00tsize\x00123\x00", + ); + + assert_eq!( + Packet::OptionalAck(OptionalAck { + extensions: Default::default(), + }) + .to_bytes() + .as_slice(), + b"\x00\x06" + ); + } + + #[test] + fn test_unknown_extensions_ignored() { + let packet = + OptionalAck::from_bytes(b"BLKSIZE\x001252\x00unknown\x001252\x00TSIZE\x0012\x00") + .unwrap(); + assert_eq!(packet.extensions.len(), 2, "{packet:?}"); + assert_eq!( + packet.extensions[&Extension::BlockSize], + ExtensionValue::from_str("1252").unwrap() + ); + assert_eq!( + packet.extensions[&Extension::TransferSize], + ExtensionValue::from_str("12").unwrap() + ); + } + + #[test] + fn test_byte_retrieval() { + let bytes = b"\x01\x02\x03\x04\x05\x06"; + assert_eq!(Some([1, 2, 3].as_slice()), bytes.get(0..3)); + assert_eq!(Some([1, 2, 3].as_slice()), bytes.get(..3)); + assert_eq!(Some([4, 5, 6].as_slice()), bytes.get(3..)); + assert_eq!(Some([4, 5, 6].as_slice()), bytes.get(3..6)); + assert_eq!(Some([].as_slice()), bytes.get(6..)); + assert_eq!(None, bytes.get(7..)); + assert_eq!(Some(&1_u8), bytes.first()); + assert_eq!(None, bytes.get(6)); + } + + #[test] + fn test_error_code() { + assert_eq!(ErrorCode::from_repr(1), Some(ErrorCode::FileNotFound)); + assert_eq!(1, ErrorCode::FileNotFound as u16); + } +} diff --git a/src/server/connection.rs b/src/server/connection.rs new file mode 100644 index 0000000..a2e758f --- /dev/null +++ b/src/server/connection.rs @@ -0,0 +1,408 @@ +use core::{cmp::min, time::Duration}; + +use log::{debug, error}; +use rand::{CryptoRng, RngCore}; + +use super::{extensions::create_options, validation::validate_request_options}; +use crate::{ + config::{ConnectionOptions, ENCRYPTION_TAG_SIZE}, + encryption::{ + overwrite_data_packet, EncryptionKeys, EncryptionLevel, Encryptor, FinalizeKeysCallback, + FinalizedKeys, Nonce, PrivateKey, PublicKey, + }, + error::{BoxedResult, EncryptionError, ExtensionError, FileError}, + map::Entry, + packet::{ + ByteConverter, ErrorCode, ErrorPacket, Extension, Packet, PacketExtensions, PacketType, + RequestPacket, + }, + server::ServerConfig, + socket::Socket, + std_compat::{ + io::{self, Read, Seek, Write}, + net::SocketAddr, + time::Instant, + }, + storage::{FileReader, FileWriter}, + string::format_str, + types::{DataBuffer, FilePath}, +}; + +pub enum ClientType { + Reader(FileReader), + Writer(FileWriter), +} + +pub struct Connection { + pub socket: S, + pub options: ConnectionOptions, + pub encryptor: Option, + pub last_updated: Instant, + pub transfer: usize, + pub client_type: ClientType, + pub endpoint: SocketAddr, +} + +impl Connection { + pub fn recv_from( + &self, + buffer: &mut DataBuffer, + wait_for: Option, + ) -> io::Result<(usize, SocketAddr)> { + self.socket.recv_from(buffer, wait_for) + } + + pub fn receive_packet(&self, _buffer: &mut DataBuffer) -> bool { + #[cfg(feature = "encryption")] + if let (EncryptionLevel::Protocol | EncryptionLevel::Full, Some(encryptor)) = + (self.options.encryption_level, &self.encryptor) + { + if encryptor.decrypt(_buffer).is_err() { + error!("Failed to decrypt packet {:x?}", &_buffer); + return false; + } + } + + #[cfg(feature = "encryption")] + if let (Ok(PacketType::Data), EncryptionLevel::Data, Some(encryptor)) = ( + PacketType::from_bytes(&_buffer), + self.options.encryption_level, + &self.encryptor, + ) { + if let Err(_) = overwrite_data_packet(_buffer, |buf| encryptor.decrypt(buf)) { + error!("Failed to decrypt data {:x?}", &_buffer); + return false; + } + } + + return true; + } + + pub fn send_packet(&self, packet: Packet) -> bool { + let packet_name = packet.packet_type(); + match &packet { + Packet::Data(d) => debug!("Send {} {} {}", packet_name, d.block, self.endpoint), + Packet::Ack(d) => debug!("Send {} {} {}", packet_name, d.block, self.endpoint), + _ => debug!("Send {} {}", packet_name, self.endpoint), + }; + + let mut data = packet.to_bytes(); + + #[cfg(feature = "encryption")] + if let (EncryptionLevel::Protocol | EncryptionLevel::Full, Some(encryptor)) = + (self.options.encryption_level, &self.encryptor) + { + if encryptor.encrypt(&mut data).is_err() { + error!("Failed to encrypt data {:x?}", &data); + return false; + } + } + #[cfg(feature = "encryption")] + if let (EncryptionLevel::Data, Some(encryptor)) = + (self.options.encryption_level, &self.encryptor) + { + if overwrite_data_packet(&mut data, |buf| encryptor.encrypt(buf)).is_err() { + error!("Failed to encrypt data {:x?}", &data); + return false; + } + } + if let Err(e) = self.socket.send_to(&mut data, self.endpoint) { + error!("Failed to send {} for {} {}", packet_name, self.endpoint, e); + return false; + } + true + } +} + +pub struct ConnectionBuilder<'a> { + config: &'a ServerConfig, + options: ConnectionOptions, + used_extensions: PacketExtensions, + file_name: Option, + finalized_keys: Option, +} + +impl<'a> ConnectionBuilder<'a> { + #[allow(unused_variables)] + pub fn from_new_connection( + config: &'a ServerConfig, + buffer: &mut DataBuffer, + rng: impl CryptoRng + RngCore + Copy, + ) -> Result { + let mut options = ConnectionOptions::default(); + #[cfg(feature = "encryption")] + let finalized_keys = if let Ok(Some((ignore, finalized_keys, remote_public_key))) = + handle_encrypted(&config.private_key, buffer, rng) + { + let can_access = if let Some(keys) = &config.authorized_keys { + let result = keys.contains(&remote_public_key); + if !result { + debug!( + "Received new connection however public key was not authorized {:x?}", + remote_public_key + ); + } + result + } else { + true + }; + if can_access { + let mut data: DataBuffer = buffer[ignore..].iter().copied().collect(); + if finalized_keys.encryptor.decrypt(&mut data).is_err() { + error!("Failed to decrypt initial connection"); + None + } else { + *buffer = data; + options.encryption_keys = Some(EncryptionKeys::LocalToRemote( + finalized_keys.public, + remote_public_key, + )); + options.encryption_level = EncryptionLevel::Full; + Some(finalized_keys) + } + } else { + None + } + } else { + None + }; + + #[cfg(feature = "encryption")] + if finalized_keys.is_none() && config.required_full_encryption { + return Err(ExtensionError::ServerRequiredEncryption( + EncryptionLevel::Full, + )); + } + + #[cfg(not(feature = "encryption"))] + let finalized_keys = None; + Ok(Self { + config, + options, + finalized_keys, + used_extensions: PacketExtensions::new(), + file_name: None, + }) + } + + pub fn with_request( + &mut self, + request: RequestPacket, + max_window_size: u16, + rng: impl CryptoRng + RngCore + Copy, + ) -> BoxedResult<()> { + let (used_extensions, options, finalized_keys) = create_options( + request.extensions, + self.options.clone(), + self.config, + self.finalized_keys.take(), + max_window_size, + rng, + )?; + self.file_name = Some(request.file_name); + self.used_extensions = used_extensions; + self.options = options; + self.finalized_keys = finalized_keys; + Ok(()) + } + + pub(crate) fn build_writer( + mut self, + socket: &S, + client: SocketAddr, + create_writer: &CreateWriter, + create_socket: &CreateSocket, + instant: fn() -> Instant, + ) -> BoxedResult<(Connection, PacketExtensions, Option)> + where + S: Socket, + W: Write + Seek, + CreateSocket: Fn(&str, usize) -> BoxedResult, + CreateWriter: Fn(&FilePath, &ServerConfig) -> BoxedResult, + { + let file_name = self.file_name.ok_or_else(|| FileError::InvalidFileName)?; + let (encryptor, finalized_keys) = if self.options.encryption_level != EncryptionLevel::Full + { + (None, self.finalized_keys.take()) + } else { + (self.finalized_keys.map(|f| f.encryptor), None) + }; + let file_path = validate_request_options( + socket, + client, + &file_name, + &self.options, + &self.used_extensions, + self.config, + )?; + + let writer = match create_writer(&file_path, &self.config) { + Ok(w) => w, + Err(e) => { + error!("Failed to open file {} {}", file_path, e); + + let packet = Packet::Error(ErrorPacket::new( + ErrorCode::DiskFull, + format_str!(DefaultString, "Unable to write file {}", file_name), + )); + socket.send_to(&mut packet.to_bytes(), client)?; + return Err(e); + } + }; + let new_socket = if self.config.require_server_port_change { + let listen = format_str!(DefaultString, "{}:{}", self.config.listen.ip(), 0); + create_socket(&listen, 0)? + } else { + socket.try_clone()? + }; + Ok(( + Connection { + socket: new_socket, + last_updated: instant(), + transfer: 0, + client_type: ClientType::Writer(FileWriter::from_writer( + writer, + self.options.block_size, + self.config.max_queued_blocks_writer, + self.options.window_size, + )), + options: self.options, + endpoint: client, + encryptor, + }, + self.used_extensions, + finalized_keys, + )) + } + + pub fn build_reader( + mut self, + socket: &S, + client: SocketAddr, + create_reader: &CreateReader, + create_socket: &CreateSocket, + instant: fn() -> Instant, + ) -> BoxedResult<(Connection, PacketExtensions, Option)> + where + S: Socket, + CreateSocket: Fn(&str, usize) -> BoxedResult, + R: Read + Seek, + CreateReader: Fn(&FilePath, &ServerConfig) -> BoxedResult<(Option, R)>, + { + let file_name = self.file_name.ok_or_else(|| FileError::InvalidFileName)?; + let (encryptor, finalized_keys) = if self.options.encryption_level != EncryptionLevel::Full + { + (None, self.finalized_keys.take()) + } else { + (self.finalized_keys.map(|f| f.encryptor), None) + }; + let file_path = validate_request_options( + socket, + client, + &file_name, + &self.options, + &self.used_extensions, + self.config, + )?; + let (transfer_size, reader) = match create_reader(&file_path, &self.config) { + Ok(f) => f, + Err(e) => { + error!("Failed to open file {} {}", file_path, e); + let packet = Packet::Error(ErrorPacket::new( + ErrorCode::DiskFull, + format_str!(DefaultString, "Unable to read file {}", file_name), + )); + socket.send_to(&mut packet.to_bytes(), client)?; + return Err(e); + } + }; + + self.options.file_size = transfer_size; + // we know about the filesize once reader is created + match ( + self.options.file_size, + self.used_extensions.entry(Extension::TransferSize), + ) { + (Some(s), Entry::Occupied(mut entry)) if s > 0 => { + *entry.get_mut() = format_str!(ExtensionValue, "{}", s); + } + (None, Entry::Occupied(mut entry)) => { + entry.remove(); + } + _ => (), + }; + + let block_reader = FileReader::from_reader( + reader, + self.config.max_queued_blocks_reader, + self.options.block_size, + self.options.retry_packet_after_timeout, + instant, + self.options.window_size, + ); + let new_socket = if self.config.require_server_port_change { + let listen = format_str!(DefaultString, "{}:{}", self.config.listen.ip(), 0); + create_socket(&listen, 0)? + } else { + socket.try_clone()? + }; + Ok(( + Connection { + socket: new_socket, + transfer: 0, + client_type: ClientType::Reader(block_reader), + options: self.options, + endpoint: client, + encryptor, + last_updated: instant(), + }, + self.used_extensions, + finalized_keys, + )) + } +} + +#[cfg(feature = "encryption")] +fn handle_encrypted( + private_key: &Option, + data: &mut DataBuffer, + rng: impl CryptoRng + RngCore + Copy, +) -> Result, EncryptionError> { + use core::mem::size_of; + + use crate::{ + encryption::{FinalizedKeys, Nonce, PrivateKey, PublicKey}, + key_management::create_finalized_keys, + }; + // as long as we dont use standard packet type this should be good. randomize ? + match PacketType::from_bytes(data) { + Ok(PacketType::InitialEncryption) => (), + _ => return Ok(None), + }; + let remote_public_key: [u8; size_of::()] = data + .get(size_of::()..size_of::() + size_of::()) + .map(|n| n.try_into()) + .transpose() + .map_err(|_| EncryptionError::Decrypt)? + .ok_or(EncryptionError::Decrypt)?; + + let remote_nonce: [u8; size_of::()] = data + .get( + size_of::() + size_of::() + ..size_of::() + size_of::() + size_of::(), + ) + .map(|n| n.try_into()) + .transpose() + .map_err(|_| EncryptionError::Decrypt)? + .ok_or(EncryptionError::Decrypt)?; + + let remote_key = remote_public_key.into(); + let mut finalized_keys = + create_finalized_keys(private_key, &remote_key, Some(remote_nonce.into()), rng); + // finalized_keys.encryptor.nonce = remote_nonce.into(); + Ok(Some(( + size_of::() + size_of::() + size_of::(), + finalized_keys, + remote_key, + ))) +} diff --git a/src/server/extensions.rs b/src/server/extensions.rs new file mode 100644 index 0000000..b4da365 --- /dev/null +++ b/src/server/extensions.rs @@ -0,0 +1,295 @@ +use core::time::Duration; + +use log::{debug, error, warn}; +use rand::{CryptoRng, RngCore}; + +use crate::{ + config::{ + ConnectionOptions, ENCRYPTION_TAG_SIZE, EXTENSION_BLOCK_SIZE_MIN, + EXTENSION_TIMEOUT_SIZE_MAX, EXTENSION_TIMEOUT_SIZE_MIN, EXTENSION_WINDOW_SIZE_MIN, + }, + encryption::{ + decode_public_key, encode_nonce, encode_public_key, EncryptionKeys, EncryptionLevel, + FinalizeKeysCallback, FinalizedKeys, + }, + error::ExtensionError, + key_management::create_finalized_keys, + map::Entry, + packet::{Extension, PacketExtensions, PacketType}, + server::ServerConfig, + string::format_str, +}; + +#[allow(unused_variables)] +pub fn create_options( + extensions: PacketExtensions, + mut options: ConnectionOptions, + config: &ServerConfig, + finalized_keys: Option, + max_window_size: u16, + rng: impl CryptoRng + RngCore + Copy, +) -> Result<(PacketExtensions, ConnectionOptions, Option), ExtensionError> { + let mut used_extensions = PacketExtensions::new(); + if let Some(size) = extensions.get(&Extension::BlockSize) { + let client_block_size: u16 = size.parse().unwrap_or(0); + if (EXTENSION_BLOCK_SIZE_MIN..=config.max_block_size).contains(&client_block_size) { + options.block_size = client_block_size; + used_extensions.insert( + Extension::BlockSize, + format_str!(ExtensionValue, "{}", options.block_size), + ); + } else if client_block_size > config.max_block_size { + options.block_size = config.max_block_size; + used_extensions.insert( + Extension::BlockSize, + format_str!(ExtensionValue, "{}", options.block_size), + ); + } else { + warn!("Invalid block size received {} skipping", size); + } + } + + if let Some(window_size) = extensions.get(&Extension::WindowSize) { + let client_window_size: u16 = window_size.parse().unwrap_or(0); + if (EXTENSION_WINDOW_SIZE_MIN..=max_window_size).contains(&client_window_size) { + options.window_size = client_window_size; + used_extensions.insert( + Extension::WindowSize, + format_str!(ExtensionValue, "{}", options.window_size), + ); + } else if client_window_size > max_window_size { + options.window_size = max_window_size; + used_extensions.insert( + Extension::WindowSize, + format_str!(ExtensionValue, "{}", options.window_size), + ); + } else { + warn!( + "Invalid window size received {} skipping", + client_window_size + ); + } + } + + if let Some(timeout) = extensions.get(&Extension::Timeout) { + let client_retry_seconds: u8 = timeout.parse().unwrap_or(0); + if (EXTENSION_TIMEOUT_SIZE_MIN..=EXTENSION_TIMEOUT_SIZE_MAX).contains(&client_retry_seconds) + { + options.retry_packet_after_timeout = Duration::from_secs(client_retry_seconds as u64); + used_extensions.insert( + Extension::Timeout, + format_str!(ExtensionValue, "{}", client_retry_seconds), + ); + } else { + warn!("Invalid retry timeout received {} skipping", timeout); + } + } + + if let Some(size) = extensions.get(&Extension::TransferSize) { + match size.parse() { + Ok(c) => { + options.file_size = Some(c); + used_extensions.insert( + Extension::TransferSize, + format_str!(ExtensionValue, "{}", c), + ); + } + Err(_) => { + warn!("Invalid transfer size received {} skipping", size); + } + } + } + + #[cfg(feature = "encryption")] + let finalized_keys = if finalized_keys.is_none() { + // allow only authorized keys and encryption + if let (Some(keys), public) = ( + &config.authorized_keys, + extensions.get(&Extension::PublicKey), + ) { + match public + .map(|p| decode_public_key(p.as_bytes())) + .transpose()? + { + Some(remote_public_key) if keys.contains(&remote_public_key) => (), + _ => { + debug!("Received new connection options however public key was not authorized",); + return Err(ExtensionError::InvalidPublicKey); + } + } + } + + if let (Some(public), Some(nonce), Some(Ok(level))) = ( + extensions.get(&Extension::PublicKey), + extensions.get(&Extension::Nonce), + extensions + .get(&Extension::EncryptionLevel) + .map(|s| s.parse()), + ) { + let remote_public_key = decode_public_key(public.as_bytes())?; + let final_keys = + create_finalized_keys(&config.private_key, &remote_public_key, None, rng); + used_extensions.insert( + Extension::PublicKey, + encode_public_key(&final_keys.public).expect("public key encoder"), + ); + used_extensions.insert( + Extension::Nonce, + encode_nonce(&final_keys.nonce()).expect("nonce encoder"), + ); + options.encryption_keys = Some(EncryptionKeys::LocalToRemote( + final_keys.public, + remote_public_key, + )); + options.encryption_level = match level { + EncryptionLevel::OptionalData => EncryptionLevel::Data, + EncryptionLevel::OptionalProtocol => EncryptionLevel::Protocol, + _ => level, + }; + used_extensions.insert( + Extension::EncryptionLevel, + format_str!(ExtensionValue, "{}", options.encryption_level), + ); + final_keys.into() + } else { + None + } + } else { + finalized_keys + }; + + #[cfg(feature = "encryption")] + if finalized_keys.is_some() + && matches!( + options.encryption_level, + EncryptionLevel::Data | EncryptionLevel::Protocol | EncryptionLevel::Full + ) + { + options.block_size -= ENCRYPTION_TAG_SIZE as u16; + } + debug!("Server extensions {:?}", used_extensions); + Ok((used_extensions, options, finalized_keys)) +} + +#[cfg(test)] +mod tests { + use rand::rngs::OsRng; + + use super::*; + #[cfg(feature = "encryption")] + use crate::encryption::{ + decode_nonce, decode_private_key, FinalizedKeys, InitialKeys, PrivateKey, PublicKey, + }; + use crate::types::FilePath; + + #[test] + fn test_parse_extensions() { + let extensions = PacketExtensions::new(); + let options = ConnectionOptions::default(); + let (extensions, ..) = + create_options(extensions, options, &create_config(), None, 8, OsRng).unwrap(); + assert_eq!(extensions.len(), 0); + + let options = ConnectionOptions::default(); + let mut extensions = PacketExtensions::new(); + extensions.insert(Extension::BlockSize, "500".parse().unwrap()); + extensions.insert(Extension::TransferSize, "6".parse().unwrap()); + extensions.insert(Extension::Timeout, "7".parse().unwrap()); + extensions.insert(Extension::WindowSize, "8".parse().unwrap()); + let (extensions, options, _) = + create_options(extensions, options, &create_config(), None, 8, OsRng).unwrap(); + assert_eq!(extensions.len(), 4, "{:?}", extensions); + assert_eq!(options.window_size, 8); + assert_eq!(options.block_size, 101); + assert_eq!(options.file_size, Some(6)); + assert_eq!(options.retry_packet_after_timeout, Duration::from_secs(7)); + } + + #[test] + fn test_parse_invalid_extensions() { + let options = ConnectionOptions::default(); + let extensions = PacketExtensions::new(); + let (extensions, ..) = + create_options(extensions, options, &create_config(), None, 8, OsRng).unwrap(); + assert_eq!(extensions.len(), 0); + + let options = ConnectionOptions::default(); + let mut extensions = PacketExtensions::new(); + extensions.insert(Extension::BlockSize, "1".parse().unwrap()); + extensions.insert(Extension::TransferSize, "a".parse().unwrap()); + extensions.insert(Extension::Timeout, "0".parse().unwrap()); + extensions.insert(Extension::WindowSize, "0".parse().unwrap()); + let (extensions, options, _) = + create_options(extensions, options, &create_config(), None, 8, OsRng).unwrap(); + assert_eq!(extensions.len(), 0); + assert_ne!(options.block_size, 1); + assert_ne!(options.file_size, Some(0)); + assert_ne!(options.retry_packet_after_timeout, Duration::from_secs(0)); + } + + #[cfg(feature = "encryption")] + #[test] + fn test_parse_extensions_encryption() { + use chacha20poly1305::aead::OsRng; + + use crate::encryption::{ + decode_nonce, decode_private_key, EncryptionLevel, Encryptor, FinalizedKeys, + InitialKeys, + }; + + let options = ConnectionOptions::default(); + let mut extensions = PacketExtensions::new(); + extensions.insert( + Extension::PublicKey, + "Yhk58FaJO5dnct6VgrfRXtjqd9m3h2JHrD/Jecov2wY=" + .parse() + .unwrap(), + ); + extensions.insert( + Extension::Nonce, + "Tw2EobyajLuhvFY9WNMfIFK7GGWqOCfI".parse().unwrap(), + ); + + extensions.insert(Extension::EncryptionLevel, "none".parse().unwrap()); + let (extensions, options, _) = + create_options(extensions, options, &create_config(), None, 8, OsRng).unwrap(); + assert_eq!(extensions.len(), 3); + assert_eq!(options.encryption_level, EncryptionLevel::None); + } + + fn create_config() -> ServerConfig { + let listen: std::net::SocketAddr = "127.0.0.1:0".parse().unwrap(); + #[cfg(not(feature = "std"))] + let listen = std_to_socket_addr(listen); + ServerConfig { + listen, + directory: FilePath::new(), + allow_overwrite: false, + max_queued_blocks_reader: 1, + max_queued_blocks_writer: 1, + request_timeout: Duration::from_millis(1), + max_connections: 1, + max_file_size: 1, + max_block_size: 101, + authorized_keys: None, + private_key: None, + required_full_encryption: false, + require_server_port_change: false, + max_window_size: 8, + } + } + + #[cfg(not(feature = "std"))] + fn std_to_socket_addr(addr: std::net::SocketAddr) -> crate::std_compat::net::SocketAddr { + match addr { + std::net::SocketAddr::V4(a) => crate::std_compat::net::SocketAddr { + ip: crate::std_compat::net::IpVersion::Ipv4(a.ip().octets()), + port: a.port(), + }, + std::net::SocketAddr::V6(a) => crate::std_compat::net::SocketAddr { + ip: crate::std_compat::net::IpVersion::Ipv6(a.ip().octets()), + port: a.port(), + }, + } + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..f6b2fdd --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,6 @@ +mod connection; +mod extensions; +mod server; +mod validation; + +pub use server::*; diff --git a/src/server/server.rs b/src/server/server.rs new file mode 100644 index 0000000..9e658f0 --- /dev/null +++ b/src/server/server.rs @@ -0,0 +1,498 @@ +use core::{cmp::max, mem::size_of_val, time::Duration}; + +use log::{debug, error, info, warn}; +use rand::{CryptoRng, RngCore}; + +use crate::{ + config::{ + print_options, ConnectionOptions, DATA_PACKET_HEADER_SIZE, MAX_BLOCKS_READER, + MAX_BLOCKS_WRITER, MAX_BUFFER_SIZE, MIN_BUFFER_SIZE, + }, + encryption::{encode_public_key, FinalizeKeysCallback, PrivateKey, PublicKey}, + error::{BoxedResult, DefaultBoxedResult, StorageError}, + map::{Entry, Map}, + packet::{ + AckPacket, ByteConverter, DataPacket, ErrorCode, ErrorPacket, OptionalAck, Packet, + PacketType, + }, + server::{ + connection::{ClientType, Connection, ConnectionBuilder}, + validation::handle_file_size, + }, + socket::Socket, + std_compat::{ + io::{ErrorKind, Read, Seek, Write}, + net::SocketAddr, + }, + storage::{BlockReader, BlockWriter}, + string::format_str, + time::InstantCallback, + types::{DataBuffer, DefaultString, FilePath}, +}; + +#[cfg(feature = "alloc")] +type Clients = Map>; +#[cfg(not(feature = "alloc"))] +type Clients = + Map, { crate::config::MAX_CLIENTS as usize }>; + +#[cfg(all(feature = "alloc", feature = "encryption"))] +pub type AuthorizedKeys = alloc::vec::Vec; +#[cfg(all(not(feature = "alloc"), feature = "encryption"))] +pub type AuthorizedKeys = heapless::Vec; +#[cfg(not(feature = "encryption"))] +pub type AuthorizedKeys = (); + +pub struct ServerConfig { + pub listen: SocketAddr, + pub directory: FilePath, + pub allow_overwrite: bool, + pub max_queued_blocks_reader: u16, + pub max_queued_blocks_writer: u16, + pub max_window_size: u16, + pub request_timeout: Duration, + pub max_connections: u16, + pub max_file_size: u64, + pub max_block_size: u16, + pub authorized_keys: Option, + pub private_key: Option, + pub required_full_encryption: bool, + pub require_server_port_change: bool, +} + +pub fn server( + config: ServerConfig, + create_reader: CreateReader, + create_writer: CreateWriter, + create_socket: CreateSocket, + instant: InstantCallback, + mut rng: Rng, +) -> DefaultBoxedResult +where + S: Socket, + Rng: CryptoRng + RngCore + Copy, + R: Read + Seek, + CreateSocket: Fn(&str, usize) -> BoxedResult, + CreateReader: Fn(&FilePath, &ServerConfig) -> BoxedResult<(Option, R)>, + W: Write + Seek, + CreateWriter: Fn(&FilePath, &ServerConfig) -> BoxedResult, +{ + info!("Starting server on {}", config.listen); + + let max_buffer_size = max( + config.max_block_size + DATA_PACKET_HEADER_SIZE as u16, + MIN_BUFFER_SIZE, + ); + assert!(max_buffer_size <= MAX_BUFFER_SIZE); + #[allow(unused_must_use)] + let mut buffer = { + let mut d = DataBuffer::new(); + d.resize(max_buffer_size as usize, 0); + d + }; + let mut clients: Clients<_, _, _> = Clients::new(); + debug!( + "Size of all clients in memory {} bytes", + size_of_val(&clients) + ); + + #[cfg(feature = "encryption")] + if let Some(private_key) = config.private_key.as_ref() { + info!( + "Server public key {}", + encode_public_key(&PublicKey::from(private_key))? + ); + } + + let listen = format_str!( + DefaultString, + "{}:{}", + &config.listen.ip(), + &config.listen.port() + ); + let socket = create_socket(&listen, 1)?; + let mut timeout_duration = instant(); + let mut last_socket_addr: Option = None; + let mut no_work: u8 = 0; + loop { + if timeout_duration.elapsed() > Duration::from_secs(2) { + timeout_clients(&mut clients, config.request_timeout); + timeout_duration = instant(); + } + let send_duration = instant(); + let sent = send_data_blocks(&mut clients); + if sent > 0 { + no_work = 1; + } else { + no_work = no_work.wrapping_add(1); + } + + debug!( + "Total clients {} sent {} packets in {}s", + clients.len(), + sent, + send_duration.elapsed().as_secs_f32() + ); + + #[cfg(feature = "alloc")] + buffer.resize(max_buffer_size as usize, 0); + // TODO heapless vector resizing is super slow + #[cfg(not(feature = "alloc"))] + unsafe { + buffer.set_len(max_buffer_size as usize) + }; + let wait_for = if clients.is_empty() { + Duration::from_millis(500).into() + } else if no_work > 2 { + Duration::from_millis(no_work as u64).into() + } else { + None + }; + let (mut received_length, from_client) = match socket.recv_from(&mut buffer, wait_for) { + Ok(n) => { + no_work = 1; + n + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + if config.require_server_port_change { + let mut recv = None; + for (s, c) in clients.iter() { + if last_socket_addr == Some(*s) { + continue; + } + match c.recv_from(&mut buffer, None) { + Ok(n) => { + recv = Some(n); + no_work = 1; + break; + } + _ => continue, + } + } + if let Some(p) = recv { + last_socket_addr = Some(p.1); + p + } else { + last_socket_addr = None; + continue; + } + } else { + no_work = no_work.wrapping_add(1); + continue; + } + } + Err(e) => return Err(e.into()), + }; + buffer.truncate(received_length); + let client_length = clients.len(); + + match clients.entry(from_client) { + Entry::Occupied(mut entry) => { + let mut connection = entry.get_mut(); + if !connection.receive_packet(&mut buffer) { + continue; + } + + let packet_type = PacketType::from_bytes(&buffer); + if !matches!( + packet_type, + Ok(PacketType::Data | PacketType::Ack | PacketType::Error) + ) { + debug!("Incorrect packet type received {:x?}", buffer); + continue; + } + + match Packet::from_bytes(&buffer) { + Ok(Packet::Data(p)) => { + let data_length = p.data.len(); + + debug!( + "Packet received block {} size {} total {} block size {} from {}", + p.block, + data_length, + connection.transfer, + connection.options.block_size, + from_client + ); + + match write_block(&mut connection, p.block, p.data) { + Ok(n) if n > 0 => { + connection.last_updated = instant(); + connection.transfer += n; + } + Ok(_) => continue, + Err(e) => { + connection.send_packet(Packet::Error(e)); + entry.remove(); + continue; + } + } + + // this would write more than expected but only by a block size maximum + if let Err(e) = + handle_file_size(connection.transfer as u64, config.max_file_size) + { + connection.send_packet(Packet::Error(e)); + entry.remove(); + continue; + } + } + Ok(Packet::Ack(p)) => { + let ClientType::Reader(ref mut block_reader): ClientType = connection.client_type else { + continue; + }; + + debug!("Ack received {} {}", p.block, from_client); + + if block_reader.free_block(p.block) > 0 { + connection.last_updated = instant(); + } + if block_reader.is_finished() { + info!("Client read {} finished", from_client); + entry.remove(); + continue; + } + } + Ok(Packet::Error(p)) => { + error!("Error received {:?} {}", p.code, p.message); + entry.remove(); + continue; + } + _ => { + debug!("Incorrect packet received {:x?}", buffer); + continue; + } + }; + } + Entry::Vacant(entry) => { + if client_length >= config.max_connections as usize { + error!( + "Max connections {} reached. Ignoring connection from {}", + config.max_connections, from_client + ); + continue; + } + + let mut builder = + match ConnectionBuilder::from_new_connection(&config, &mut buffer, rng) { + Ok(b) => b, + Err(e) => { + debug!("New connection error {}", e); + continue; + } + }; + + if !matches!( + PacketType::from_bytes(&buffer), + Ok(PacketType::Write | PacketType::Read) + ) { + debug!("Incorrect packet type received {:x?}", buffer); + continue; + } + + debug!("Received from new client {}", from_client); + + match Packet::from_bytes(&buffer) { + Ok(Packet::Write(p)) => { + debug!( + "New client writing to file {} in directory {}", + p.file_name, config.directory + ); + + let Ok(()) = builder.with_request(p, config.max_window_size, rng) else { + continue; + }; + + let Ok((mut connection, used_extensions, encrypt_new_connection)): Result<(Connection<_, W, _>, _, _), _> = + builder.build_writer(&socket, from_client, &create_writer, &create_socket, instant) + else { + continue; + }; + + if !used_extensions.is_empty() { + if !connection.send_packet(Packet::OptionalAck(OptionalAck { + extensions: used_extensions, + })) { + continue; + } + } else if !connection.send_packet(Packet::Ack(AckPacket { block: 0 })) { + continue; + } + // // new encryption starts only here + if let Some(keys) = encrypt_new_connection { + connection.encryptor = keys.encryptor.into(); + } + + print_options("Server writing using", &connection.options); + + entry.insert(connection); + } + Ok(Packet::Read(p)) => { + debug!( + "New client reading file {} in directory {}", + p.file_name, config.directory + ); + + let Ok(()) = builder.with_request(p, config.max_window_size, rng) else { + continue; + }; + + let Ok((mut connection, used_extensions, encrypt_new_connection)): Result<(Connection, _, _), _> = + builder.build_reader(&socket, from_client, &create_reader, &create_socket, instant) else { + continue; + }; + + if !used_extensions.is_empty() { + if !connection.send_packet(Packet::OptionalAck(OptionalAck { + extensions: used_extensions, + })) { + continue; + } + } + + // new encryption starts only here + if let Some(keys) = encrypt_new_connection { + connection.encryptor = keys.encryptor.into(); + } + + print_options("Server reading using", &connection.options); + + entry.insert(connection); + } + _ => { + debug!("Incorrect packet received {:x?}", buffer); + continue; + } + }; + } + } + } +} + +fn write_block( + connection: &mut Connection, + mut block: u16, + data: &[u8], +) -> Result +where + S: Socket, +{ + let ClientType::Writer(ref mut block_writer): ClientType<_, W> = connection.client_type else { + return Ok(0); + }; + let (length, last_in_window) = match block_writer.write_block(block, data) { + Ok((n, l)) => { + debug!("Write block {} written size {}", block, n); + (n, l) + } + Err(StorageError::ExpectedBlock((expected, current))) => { + debug!("Received unexpected block {} expecting {}", block, expected); + block = current; + (0, true) + } + Err(StorageError::AlreadyWriten) => { + debug!( + "Received block that was written before. Ignoring block {}", + block + ); + (0, true) + } + Err(StorageError::CapacityReached) => { + debug!( + "Capacity reached waiting for previous blocks. Ignoring block {}", + block + ); + return Ok(0); + } + Err(e) => { + error!("Failed to write block {} {}", block, e); + return Err(ErrorPacket::new( + ErrorCode::AccessVioliation, + format_str!(DefaultString, "{}", e), + )); + } + }; + + if connection.options.window_size <= 1 + || last_in_window + || block_writer.is_finished_below(connection.options.block_size) + { + if !connection.send_packet(Packet::Ack(AckPacket { block })) { + error!("Unable to ack block {}", block); + } + } + Ok(length) +} + +fn timeout_clients( + clients: &mut Clients, + request_timeout: Duration, +) { + clients.retain(|client, connection| { + let client_type = match connection.client_type { + ClientType::Writer(ref w) => { + if w.is_finished_below(connection.options.block_size) { + info!("Client write finished {}", client); + return false; + } + "write" + } + ClientType::Reader(_) => "read", + }; + if connection.last_updated.elapsed() <= request_timeout { + return true; + } + + warn!( + "Client {} timeout {} {}", + client_type, + client, + connection.last_updated.elapsed().as_secs_f32() + ); + + let message = format_str!( + DefaultString, + "Client timeout {}", + connection.last_updated.elapsed().as_secs_f32() + ); + connection.send_packet(Packet::Error(ErrorPacket::new( + ErrorCode::AccessVioliation, + message, + ))); + false + }); +} + +fn send_data_blocks(clients: &mut Clients) -> usize { + let mut sent = 0; + clients.retain(|_, connection| { + for _ in 0..1 { + let block_reader = match &mut connection.client_type { + ClientType::Reader(r) => r, + ClientType::Writer(_) => return true, + }; + + let packet_block = match block_reader.next() { + Ok(Some(b)) => b, + Ok(None) => return true, + Err(e) => { + error!("Failed to read {}", e); + connection.send_packet(Packet::Error(ErrorPacket::new( + ErrorCode::AccessVioliation, + format_str!(DefaultString, "{}", e), + ))); + return false; + } + }; + let packet_sent = connection.send_packet(Packet::Data(DataPacket { + block: packet_block.block, + data: &packet_block.data, + })); + if packet_sent { + sent += 1; + } + } + true + }); + sent +} diff --git a/src/server/validation.rs b/src/server/validation.rs new file mode 100644 index 0000000..1cea93f --- /dev/null +++ b/src/server/validation.rs @@ -0,0 +1,164 @@ +use log::error; + +use crate::{ + config::ConnectionOptions, + error::{BoxedResult, ExtensionError, FileError}, + packet::{ByteConverter, ErrorCode, ErrorPacket, Extension, Packet, PacketExtensions}, + server::ServerConfig, + socket::Socket, + std_compat::net::SocketAddr, + string::format_str, + types::FilePath, +}; + +pub fn validate_request_options( + socket: &impl Socket, + client: SocketAddr, + file_name: &FilePath, + options: &ConnectionOptions, + _extensions: &PacketExtensions, + config: &ServerConfig, +) -> BoxedResult { + #[cfg(feature = "encryption")] + if _extensions.get(&Extension::PublicKey).is_some() + != _extensions.get(&Extension::Nonce).is_some() + { + let (missing, provided) = if _extensions.get(&Extension::Nonce).is_some() { + ("public key", "nonce") + } else { + ("nonce", "public key") + }; + + let packet = Packet::Error(ErrorPacket::new( + ErrorCode::IllegalOperation, + format_str!( + DefaultString, + "Missing extension {} while {} provided", + missing, + provided + ), + )); + socket.send_to(&mut packet.to_bytes(), client)?; + return Err(if _extensions.get(&Extension::Nonce).is_some() { + ExtensionError::InvalidPublicKey.into() + } else { + ExtensionError::InvalidNonce.into() + }); + } + + if let Err(e) = handle_file_size(options.file_size.unwrap_or(0), config.max_file_size) { + let packet = Packet::Error(e); + socket.send_to(&mut packet.to_bytes(), client)?; + return Err(ExtensionError::InvalidExtension(Extension::TransferSize).into()); + } + + match validate_file_name(file_name) { + Ok(p) => Ok(p), + Err(e) => { + let packet = Packet::Error(e); + socket.send_to(&mut packet.to_bytes(), client)?; + return Err(FileError::InvalidFileName.into()); + } + } +} + +pub fn handle_file_size(received_size: u64, max_file_size: u64) -> Result<(), ErrorPacket> { + if received_size > max_file_size { + error!( + "Invalid file size received {} expected {}", + received_size, max_file_size, + ); + let message = format_str!( + DefaultString, + "Invalid file size received {} expected {}", + received_size, + max_file_size + ); + return Err(ErrorPacket::new(ErrorCode::DiskFull, message)); + } + Ok(()) +} + +pub fn validate_file_name(file_name: &FilePath) -> Result { + let local_file_path = match normalize_remote_name(file_name) { + Ok(p) => p, + Err(e) => { + error!("Invalid file name received {} {}", file_name.as_str(), e); + return Err(ErrorPacket::new( + ErrorCode::AccessVioliation, + format_str!(DefaultString, "Invalid file name received {}", file_name), + )); + } + }; + Ok(local_file_path) +} + +fn normalize_remote_name(file_path: &FilePath) -> Result { + #[allow(unused_must_use)] + let mut result = file_path + .as_str() + .trim_start_matches('/') + .split('/') + .filter(|c| !matches!(c.trim(), "." | ".." | "/" | "")) + .fold(FilePath::new(), |mut f, c| { + f.push_str(c); + f.push('/'); + f + }); + result.pop(); + if result.as_str().is_empty() { + return Err(FileError::InvalidFileName); + } + Ok(result) +} + +#[cfg(test)] +mod tests { + use core::str::FromStr; + + use super::*; + + #[test] + fn test_normalize_name() { + let data = [ + ("a", "a"), + ("a", "./a"), + ("a", "/a"), + ("root/a", "root/a"), + ("root/a", "/root/a"), + ("root/a/b", "root/a/../b"), + ("a", "../../a"), + ("b", "../b/../."), + (".b.", "./.b."), + (" s", "/ / / / s"), + ("s", "//s"), + ("s", "///s"), + ]; + for (i, (expected, file_path)) in data.into_iter().enumerate() { + assert_eq!( + FilePath::from_str(expected).unwrap(), + normalize_remote_name(&FilePath::from_str(file_path).unwrap()).unwrap(), + "{i}" + ); + } + } + + #[test] + fn test_normalize_name_failures() { + let data = ["", ".", "/../.", "/////"]; + for (i, file_path) in data.into_iter().enumerate() { + assert!( + normalize_remote_name(&FilePath::from_str(file_path).unwrap()).is_err(), + "{}", + i + ); + } + } + + #[cfg(not(feature = "alloc"))] + #[test] + fn test_capacity_reached() { + let file_path = "very-long-file-segment-very-long-file/very-long-file-segment-very-long-file-segment-very-long-file-segment-very-long-file-segment-very-long-file-segment"; + assert!(file_path.parse::().is_err(),); + } +} diff --git a/src/socket.rs b/src/socket.rs new file mode 100644 index 0000000..30d9cc9 --- /dev/null +++ b/src/socket.rs @@ -0,0 +1,127 @@ +use core::time::Duration; + +use crate::{ + config::ConnectionOptions, + encryption::{overwrite_data_packet, EncryptionKeys, EncryptionLevel, Encryptor, PublicKey}, + std_compat::{ + io::{Error, ErrorKind, Result}, + net::SocketAddr, + }, + types::DataBuffer, +}; + +pub trait Socket { + fn recv_from( + &self, + buf: &mut DataBuffer, + wait_for: Option, + ) -> Result<(usize, SocketAddr)>; + fn send_to(&self, buf: &mut DataBuffer, addr: SocketAddr) -> Result; + fn try_clone(&self) -> Result + where + Self: Sized; + fn local_addr(&self) -> Result; +} + +#[cfg(feature = "encryption")] +pub struct EncryptionBoundSocket { + pub socket: S, + pub encryptor: Option, + pub encryption_level: EncryptionLevel, + pub public_key: Option, +} + +#[cfg(feature = "encryption")] +impl EncryptionBoundSocket { + pub fn new( + socket: S, + encryptor: Option, + public_key: PublicKey, + encryption_level: EncryptionLevel, + ) -> Self { + Self { + socket, + encryptor, + encryption_level, + public_key: public_key.into(), + } + } + + pub fn wrap(socket: S) -> Self { + Self { + socket, + encryptor: None, + encryption_level: EncryptionLevel::None, + public_key: None, + } + } +} + +#[cfg(feature = "encryption")] +impl Socket for EncryptionBoundSocket +where + S: Socket, +{ + fn recv_from( + &self, + buff: &mut DataBuffer, + wait_for: Option, + ) -> Result<(usize, SocketAddr)> { + let (received_length, s) = self.socket.recv_from(buff, wait_for)?; + buff.truncate(received_length); + log::trace!("Received data {:x?}", buff); + match (self.encryption_level, &self.encryptor) { + (EncryptionLevel::Protocol | EncryptionLevel::Full, Some(encryptor)) => { + encryptor + .decrypt(buff) + .map_err(|_| Error::from(ErrorKind::InvalidData))?; + } + (EncryptionLevel::Data, Some(encryptor)) => { + overwrite_data_packet(buff, |buff| encryptor.decrypt(buff)) + .map_err(|_| Error::from(ErrorKind::InvalidData))?; + } + _ => (), + } + Ok((buff.len(), s)) + } + + fn send_to(&self, buff: &mut DataBuffer, endpoint: SocketAddr) -> Result { + use crate::packet::PacketType; + log::trace!("Send data {:x?}", buff); + match (self.encryption_level, &self.encryptor) { + (EncryptionLevel::Protocol | EncryptionLevel::Full, Some(encryptor)) => { + let packet_type = PacketType::from_bytes(buff); + encryptor + .encrypt(buff) + .map_err(|_| Error::from(ErrorKind::InvalidData))?; + // encrypt initial packet + if let Ok(PacketType::Read | PacketType::Write) = packet_type { + *buff = PacketType::InitialEncryption + .to_bytes() + .into_iter() + .chain(self.public_key.unwrap().as_bytes().iter().copied()) + .chain(encryptor.nonce.into_iter()) + .chain(buff.iter().copied()) + .collect(); + } + } + (EncryptionLevel::Data, Some(encryptor)) => { + overwrite_data_packet(buff, |buff| encryptor.encrypt(buff)) + .map_err(|_| Error::from(ErrorKind::InvalidData))?; + } + _ => (), + } + self.socket.send_to(buff, endpoint) + } + + fn try_clone(&self) -> Result + where + Self: Sized, + { + unimplemented!() + } + + fn local_addr(&self) -> Result { + self.socket.local_addr() + } +} diff --git a/src/std_compat.rs b/src/std_compat.rs new file mode 100644 index 0000000..8521e43 --- /dev/null +++ b/src/std_compat.rs @@ -0,0 +1,243 @@ +pub mod time { + // time in microseconds + pub type CurrentTimeCallback = fn() -> u64; + + #[derive(Debug)] + pub struct Instant { + time: CurrentTimeCallback, + init: core::time::Duration, + } + impl Instant { + pub fn from_time(time: CurrentTimeCallback) -> Instant { + Self { + time, + init: core::time::Duration::from_micros(time()), + } + } + pub fn elapsed(&self) -> core::time::Duration { + core::time::Duration::from_micros((self.time)()) - self.init + } + } +} + +pub mod io { + use crate::types::DefaultString; + + pub trait Read { + fn read(&mut self, buf: &mut [u8]) -> Result; + } + + pub trait Write { + fn write(&mut self, buf: &[u8]) -> Result; + fn write_fmt(&mut self, fmt: core::fmt::Arguments<'_>) -> Result<()>; + fn flush(&mut self) -> Result<()>; + } + + pub trait Seek { + fn seek(&mut self, pos: SeekFrom) -> Result; + } + + pub enum SeekFrom { + Start(u64), + End(i64), + Current(i64), + } + + pub trait BufRead { + fn lines(self) -> Lines + where + Self: Sized, + { + Lines { buf: self } + } + fn read_line(&mut self, buff: &mut DefaultString) -> Result; + } + + #[derive(Debug)] + pub struct Lines { + buf: B, + } + + impl Iterator for Lines { + type Item = Result; + + fn next(&mut self) -> Option> { + let mut buf = DefaultString::new(); + match self.buf.read_line(&mut buf) { + Ok(0) => None, + Ok(_n) => { + if buf.ends_with('\n') { + buf.pop(); + if buf.ends_with('\r') { + buf.pop(); + } + } + Some(Ok(buf)) + } + Err(e) => Some(Err(e)), + } + } + } + + pub type Result = core::result::Result; + + #[derive(Debug)] + pub struct Error { + kind: ErrorKind, + } + + impl From for Error { + fn from(kind: ErrorKind) -> Self { + Self { kind } + } + } + + impl Error { + pub fn kind(&self) -> ErrorKind { + self.kind.clone() + } + } + + impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.kind().as_str()) + } + } + + #[derive(PartialEq, Eq, Debug, Clone, Copy)] + pub enum ErrorKind { + NotFound, + PermissionDenied, + ConnectionRefused, + ConnectionReset, + ConnectionAborted, + NotConnected, + AddrInUse, + AddrNotAvailable, + BrokenPipe, + AlreadyExists, + WouldBlock, + InvalidInput, + InvalidData, + TimedOut, + WriteZero, + Interrupted, + UnexpectedEof, + OutOfMemory, + Other, + } + + impl ErrorKind { + pub(crate) fn as_str(&self) -> &'static str { + use ErrorKind::*; + match *self { + NotFound => "entity not found", + PermissionDenied => "permission denied", + ConnectionRefused => "connection refused", + ConnectionReset => "connection reset", + ConnectionAborted => "connection aborted", + NotConnected => "not connected", + AddrInUse => "address in use", + AddrNotAvailable => "address not available", + BrokenPipe => "broken pipe", + AlreadyExists => "entity already exists", + WouldBlock => "operation would block", + InvalidInput => "invalid input parameter", + InvalidData => "invalid dat", + TimedOut => "timed out", + WriteZero => "write zero", + Interrupted => "operation interrupted", + UnexpectedEof => "unexpected end of file", + OutOfMemory => "out of memory", + Other => "other error", + } + } + } +} + +pub mod error { + pub trait Error {} +} + +pub mod net { + #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] + pub struct SocketAddr { + pub ip: IpVersion, + pub port: u16, + } + + impl SocketAddr { + pub fn ip(&self) -> IpVersion { + self.ip + } + + pub fn port(&self) -> u16 { + self.port + } + } + #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] + pub enum IpVersion { + Ipv4([u8; 4]), + Ipv6([u8; 16]), + } + + impl hash32::Hash for SocketAddr { + fn hash(&self, state: &mut H) + where + H: hash32::Hasher, + { + match self.ip { + IpVersion::Ipv4(b) => { + let bytes: heapless::Vec = b + .into_iter() + .chain(self.port.to_be_bytes().into_iter()) + .collect(); + state.write(&bytes); + } + IpVersion::Ipv6(b) => { + let bytes: heapless::Vec = b + .into_iter() + .chain(self.port.to_be_bytes().into_iter()) + .collect(); + state.write(&bytes); + } + } + } + } + + impl core::fmt::Display for IpVersion { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + IpVersion::Ipv4(b) => { + write!(f, "{}.{}.{}.{}", b[0], b[1], b[2], b[3]) + } + IpVersion::Ipv6(b) => write!( + f, + "{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}", + b[0], + b[1], + b[2], + b[3], + b[4], + b[5], + b[6], + b[7], + b[8], + b[9], + b[10], + b[11], + b[12], + b[13], + b[14], + b[15], + ), + } + } + } + + impl core::fmt::Display for SocketAddr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}:{}", self.ip, self.port) + } + } +} diff --git a/src/storage.rs b/src/storage.rs new file mode 100644 index 0000000..caa1668 --- /dev/null +++ b/src/storage.rs @@ -0,0 +1,1005 @@ +use core::{ + cmp::{max, min}, + time::Duration, +}; + +use log::debug; + +use crate::{ + config::MAX_DATA_BLOCK_SIZE, + error::StorageError, + map::{Entry, Map}, + std_compat::{ + io::{Read, Seek, SeekFrom, Write}, + time::Instant, + }, + time::InstantCallback, + types::DataBlock, +}; + +#[cfg(feature = "alloc")] +type BlockMapWriter = Map; +#[cfg(not(feature = "alloc"))] +type BlockMapWriter = Map; +#[cfg(feature = "alloc")] +type BlockMapReader = Map; +#[cfg(not(feature = "alloc"))] +type BlockMapReader = Map; + +pub trait BlockWriter { + fn write_block(&mut self, block: u16, data: &[u8]) -> Result<(usize, bool), StorageError>; + fn is_finished_below(&self, block_size: u16) -> bool; +} + +pub struct FileWriter { + writer: T, + current_block_written: u64, + #[cfg(feature = "seek")] + allocated_blocks: BlockMapWriter, + #[cfg(not(feature = "seek"))] + allocated_blocks: BlockMapWriter, + last_block_size: Option, + block_size: u16, + max_blocks_to_allocate: u16, + #[cfg(feature = "seek")] + last_block_allocated: u64, + block_mapper: BlockMapper, + window_size: u16, +} + +impl FileWriter +where + T: Write + Seek, +{ + pub fn from_writer( + writer: T, + block_size: u16, + max_blocks_to_allocate: u16, + window_size: u16, + ) -> Self { + let max_blocks_to_allocate = if window_size > 1 { + window_size + } else { + max_blocks_to_allocate + }; + #[cfg(not(feature = "alloc"))] + assert!( + max_blocks_to_allocate <= crate::config::MAX_BLOCKS_WRITER, + "Writer blocks {} must be <= {}", + max_blocks_to_allocate, + crate::config::MAX_BLOCKS_READER + ); + Self { + writer, + current_block_written: 0, + allocated_blocks: BlockMapWriter::new(), + last_block_size: None, + block_size, + max_blocks_to_allocate, + #[cfg(feature = "seek")] + last_block_allocated: 0, + block_mapper: BlockMapper::new(), + window_size, + } + } +} + +impl BlockWriter for FileWriter +where + T: Write + Seek, +{ + fn write_block(&mut self, block: u16, data: &[u8]) -> Result<(usize, bool), StorageError> { + let expected_index = self.block_mapper.clone().index(block); + if expected_index > self.current_block_written + 1 + && expected_index - self.current_block_written > self.max_blocks_to_allocate as u64 + { + return Err(StorageError::CapacityReached); + } + let index = self.block_mapper.index(block); + if index <= self.current_block_written { + return Err(StorageError::AlreadyWriten); + } + + if self.window_size > 1 && index > self.current_block_written + 1 { + return Err(StorageError::ExpectedBlock(( + self.block_mapper.block(self.current_block_written + 1), + self.block_mapper.block(self.current_block_written), + ))); + } else { + #[cfg(feature = "seek")] + // allow to allocate what is within allowed range + if index > self.current_block_written + 1 && !self.allocated_blocks.contains_key(&index) + { + if self.current_block_written > self.last_block_allocated { + self.last_block_allocated = self.current_block_written; + } + + if index <= self.last_block_allocated { + return Err(StorageError::AlreadyWriten); + } + + // remaining block will be allocated with seek + let blocks_to_allocate = index - self.last_block_allocated - 1; + if blocks_to_allocate > 0 { + #[allow(unused_must_use)] + let mut buffer = { + let mut d = DataBlock::new(); + d.resize(self.block_size as usize, 0); + d + }; + + for _ in 0..blocks_to_allocate { + let position = + (self.last_block_allocated as usize) * self.block_size as usize; + self.writer.seek(SeekFrom::Start(position as u64))?; + self.last_block_allocated += 1; + self.allocated_blocks + .insert(self.last_block_allocated, true); + self.writer.write(&buffer)?; + } + } + self.last_block_allocated += 1; + } + #[cfg(not(feature = "seek"))] + if index > self.current_block_written + 1 { + if self.allocated_blocks.contains_key(&index) { + return Err(StorageError::AlreadyWriten); + } + if data.len() < self.block_size as usize { + self.last_block_size = Some(data.len() as u16); + } + self.allocated_blocks + .insert(index, data.iter().copied().collect()); + return Ok((0, false)); + } + } + + #[cfg(feature = "seek")] + let position = (index - 1) * self.block_size as u64; + #[cfg(feature = "seek")] + if matches!(self.writer.seek(SeekFrom::Current(0)), Ok(p) if p != position) { + self.writer.seek(SeekFrom::Start(position))?; + } + let mut written = self.writer.write(data)?; + let remaining_blocks = self.allocated_blocks.len(); + self.allocated_blocks.remove(&index); + // last packet received + if data.len() < self.block_size as usize { + self.last_block_size = Some(data.len() as u16); + } + #[cfg(feature = "seek")] + if remaining_blocks > 0 && self.allocated_blocks.is_empty() { + self.current_block_written = self.last_block_allocated; + } else if index == self.current_block_written + 1 { + self.current_block_written += 1; + } + #[cfg(not(feature = "seek"))] + { + self.current_block_written += 1; + } + #[cfg(not(feature = "seek"))] + while let Some(b) = self.allocated_blocks.get(&(self.current_block_written + 1)) { + self.current_block_written += 1; + written += self.writer.write(b)?; + self.allocated_blocks.remove(&self.current_block_written); + } + let last_in_window = self.current_block_written % self.window_size as u64 == 0; + Ok((written, last_in_window)) + } + + fn is_finished_below(&self, block_size: u16) -> bool { + self.current_block_written > 0 + && self.allocated_blocks.is_empty() + && self.last_block_size.is_some() + && self.last_block_size < Some(block_size) + } +} + +/// Since not all packet are received/acknowledged this serves as a repeater +pub trait BlockReader { + fn next(&mut self) -> Result, StorageError>; + /// release block returning data size released + fn free_block(&mut self, block: u16) -> usize; + fn is_finished(&self) -> bool; +} + +#[derive(Debug)] +pub struct FileReader { + reader: T, + blocks: BlockMapReader, + max_blocks_in_memory: u16, + file_reading_finished: bool, + current_block_read: u64, + block_size: u16, + retry_timeout: Duration, + instant: InstantCallback, + block_mapper: BlockMapper, + start_window: u64, + end_window: u64, + window_size: u16, + window_last_read: Instant, +} + +impl FileReader +where + T: Read + Seek, +{ + pub fn from_reader( + reader: T, + max_blocks_in_memory: u16, + block_size: u16, + retry_timeout: Duration, + instant: InstantCallback, + window_size: u16, + ) -> Self { + let max_blocks_in_memory = if window_size > 1 { + window_size + } else { + max_blocks_in_memory + }; + #[cfg(not(feature = "alloc"))] + assert!( + max_blocks_in_memory <= crate::config::MAX_BLOCKS_READER, + "Reader blocks {} must be <= {}", + max_blocks_in_memory, + crate::config::MAX_BLOCKS_READER + ); + Self { + reader, + blocks: BlockMapReader::::new(), + max_blocks_in_memory, + file_reading_finished: false, + current_block_read: 0, + block_size, + retry_timeout, + instant, + block_mapper: BlockMapper::new(), + start_window: 1, + end_window: window_size as u64, + window_size, + window_last_read: instant(), + } + } + + fn read_block(&mut self, block: u64) -> Result, StorageError> { + let position = (block as u64 - 1) * self.block_size as u64; + #[cfg(feature = "seek")] + if matches!(self.reader.seek(SeekFrom::Current(0)), Ok(p) if p != position) { + self.reader.seek(SeekFrom::Start(position))?; + } + #[allow(unused_must_use)] + let mut buffer = { + let mut d = DataBlock::new(); + d.resize(self.block_size as usize, 0); + d + }; + let read = self.reader.read(&mut buffer)?; + buffer.truncate(read); + Ok(Some(buffer)) + } +} + +impl BlockReader for FileReader +where + T: Read + Seek, +{ + fn next(&mut self) -> Result, StorageError> { + if self.is_finished() { + return Ok(None); + } + + if self.window_size > 1 { + if self.window_last_read.elapsed() > self.retry_timeout { + self.window_last_read = (self.instant)(); + self.current_block_read = self.start_window - 1; + } + if self.current_block_read == self.end_window { + return Ok(None); + } + } else { + let block_size = self.blocks.len() as u16; + let next = self + .blocks + .iter_mut() + .find(|(_, t)| t.last_read.elapsed() >= self.retry_timeout) + .map(|(b, t)| (b, t)); + + if next.is_some() + || block_size >= self.max_blocks_in_memory + || self.file_reading_finished + { + if let Some((index, t)) = next { + t.retry += 1; + t.last_read = (self.instant)(); + let index = *index; + let block = self.block_mapper.block(index); + debug!( + "Retried block {} index {} retries {}", + block, index, t.retry + ); + let retry = t.retry; + #[cfg(feature = "seek")] + return self.read_block(index).map(|o| { + o.map(|d| Block { + block, + data: d, + retry, + expect_ack: true, + }) + }); + #[cfg(not(feature = "seek"))] + return Ok(Some(Block { + block, + data: t.data.clone(), + retry, + expect_ack: true, + })); + } else { + return Ok(None); + }; + } + + let earliest = self + .blocks + .iter() + .min_by(|a, b| a.0.cmp(&b.0)) + .map(|(b, _)| *b); + + if let Some(b) = earliest { + if self.current_block_read - b >= self.max_blocks_in_memory as u64 { + return Ok(None); + } + } + } + + let index = self.current_block_read + 1; + #[cfg(not(feature = "seek"))] + if let Some(td) = self.blocks.get_mut(&index) { + self.window_last_read = (self.instant)(); + td.retry += 1; + td.last_read = (self.instant)(); + self.current_block_read = index; + debug!("Retried block {} {}", index, td.retry); + let block = self.block_mapper.block(index); + return Ok(Some(Block { + block, + data: td.data.clone(), + retry: td.retry, + expect_ack: if self.window_size > 1 { + self.current_block_read == self.end_window + } else { + true + }, + })); + } + let result = self.read_block(index); + if matches!(&result, Ok(Some(d)) if d.len() < self.block_size as usize) { + self.file_reading_finished = true; + self.end_window = index; + } + if let Ok(Some(d)) = &result { + self.window_last_read = (self.instant)(); + self.current_block_read = index; + self.blocks.insert( + index, + TimedBlock { + last_read: (self.instant)(), + #[cfg(not(feature = "seek"))] + data: d.clone(), + retry: 0, + size: d.len(), + }, + ); + } + let block = self.block_mapper.block(index); + result.map(|o| { + o.map(|data| Block { + block, + data, + retry: 0, + expect_ack: if self.window_size > 1 { + self.current_block_read == self.end_window + } else { + true + }, + }) + }) + } + + fn free_block(&mut self, block: u16) -> usize { + let index = self.block_mapper.index(block); + + if index > self.current_block_read { + return 0; + } + let mut size = 0; + + if self.window_size <= 1 { + size += self.blocks.remove(&index).map(|t| t.size).unwrap_or(0); + } else { + if index <= self.end_window && index >= self.start_window { + for b in self.start_window..=index { + size += self.blocks.remove(&b).map(|t| t.size).unwrap_or(0); + } + self.start_window = index + 1; + if !self.file_reading_finished { + self.end_window = self.start_window + self.window_size as u64 - 1; + } + }; + } + size + } + + fn is_finished(&self) -> bool { + self.blocks.is_empty() && self.file_reading_finished + } +} + +#[derive(Debug, Clone, Copy)] +struct BlockMapper { + current_block_set: u64, + next_block_set: u64, +} + +impl BlockMapper { + fn new() -> Self { + Self { + current_block_set: 1, + next_block_set: 1, + } + } + + fn index(&mut self, block: u16) -> u64 { + if self.current_block_set == self.next_block_set && block > u16::MAX - 10000 { + self.next_block_set += 1; + } + if self.current_block_set != self.next_block_set { + if block < 10000 { + let next_block = self.next_block_set - 1; + return (next_block * u16::MAX as u64) + block as u64 + next_block; + } else if block >= 10000 && block < 20000 { + self.current_block_set += 1; + } + } + let current_block = self.current_block_set - 1; + let mut index = (current_block * u16::MAX as u64) + block as u64; + if current_block > 0 { + index += current_block; + } + index + } + + // block index + // 0 0 + // 1 1 + // 2 2 + // 3 3 + // 4 4 + // 5 5 + // 0 6 + // 1 7 + // 2 8 + // 3 9 + // 4 10 + // 5 11 + // 0 12 + // 1 13 + // 2 14 + // 3 15 + // 4 16 + // 5 17 + // 0 18 + // 1 19 + // 2 20 + // 3 21 + fn block(&self, index: u64) -> u16 { + if index > u16::MAX as u64 { + let part = index / (u16::MAX as u64 + 1); + return (index - (part * (u16::MAX as u64 + 1))) as u16; + } + index as u16 + } +} + +#[derive(Debug)] +pub struct Block { + pub block: u16, + pub data: DataBlock, + pub retry: u16, + pub expect_ack: bool, +} + +#[derive(Debug)] +pub struct TimedBlock { + last_read: Instant, + #[cfg(not(feature = "seek"))] + data: DataBlock, + retry: u16, + size: usize, +} + +#[cfg(test)] +mod tests { + use std::{ + io::Cursor, + sync::{Arc, Mutex}, + thread::sleep, + vec::Vec, + }; + + use super::*; + + #[test] + fn test_block_write() { + let random_bytes: Vec = (0..102).map(|_| rand::random::()).collect(); + let cursor = Arc::new(Mutex::new(Cursor::new(vec![]))); + let writer = CursorWriter { + cursor: cursor.clone(), + }; + let mut block_writer = FileWriter::from_writer(writer, 20, 4, 1); + block_writer.write_block(1, &random_bytes[..20]).unwrap(); + let result = block_writer.write_block(1, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::AlreadyWriten)), + "{:?}", + result + ); + assert!(!block_writer.is_finished_below(20)); + block_writer.write_block(3, &random_bytes[40..60]).unwrap(); + block_writer.write_block(4, &random_bytes[60..80]).unwrap(); + block_writer.write_block(5, &random_bytes[80..100]).unwrap(); + let result = block_writer.write_block(6, &random_bytes[100..102]); + assert!( + matches!(result, Err(StorageError::CapacityReached)), + "{:?}", + result + ); + assert!(!block_writer.is_finished_below(20)); + block_writer.write_block(2, &random_bytes[20..40]).unwrap(); + let (result, last_in_window) = block_writer + .write_block(6, &random_bytes[100..102]) + .unwrap(); + assert_eq!(result, 2); + assert!(last_in_window); + assert!(block_writer.is_finished_below(20)); + assert_eq!(&random_bytes, cursor.lock().unwrap().get_ref()); + } + + #[test] + fn test_block_write_random_order() { + let random_bytes: Vec = (0..100).map(|_| rand::random::()).collect(); + let writer = Cursor::new(vec![]); + #[cfg(not(feature = "std"))] + let writer = CursorWriter { + cursor: Arc::new(Mutex::new(writer)), + }; + let mut block_writer = FileWriter::from_writer(writer, 20, 4, 1); + + let result = block_writer.write_block(5, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::CapacityReached)), + "{:?}", + result + ); + block_writer.write_block(1, &random_bytes[..20]).unwrap(); + block_writer.write_block(4, &random_bytes[..20]).unwrap(); + block_writer.write_block(5, &random_bytes[..20]).unwrap(); + let result = block_writer.write_block(5, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::AlreadyWriten)), + "{:?}", + result + ); + let result = block_writer.write_block(6, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::CapacityReached)), + "{:?}", + result + ); + let result = block_writer.write_block(9, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::CapacityReached)), + "{:?}", + result + ); + block_writer.write_block(2, &random_bytes[..20]).unwrap(); + block_writer.write_block(6, &random_bytes[..2]).unwrap(); + assert!(!block_writer.is_finished_below(20)); + let result = block_writer.write_block(2, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::AlreadyWriten)), + "{:?}", + result + ); + block_writer.write_block(3, &random_bytes[..20]).unwrap(); + assert!(block_writer.is_finished_below(20)); + } + + #[test] + fn test_block_write_window_size() { + let random_bytes: Vec = (0..102).map(|_| rand::random::()).collect(); + let cursor = Arc::new(Mutex::new(Cursor::new(vec![]))); + let writer = CursorWriter { + cursor: cursor.clone(), + }; + let mut block_writer = FileWriter::from_writer(writer, 20, 0, 3); + let (s, last_in_windown) = block_writer.write_block(1, &random_bytes[..20]).unwrap(); + assert_eq!(s, 20); + assert!(!last_in_windown); + let result = block_writer.write_block(1, &random_bytes[..20]); + assert!( + matches!(result, Err(StorageError::AlreadyWriten)), + "{:?}", + result + ); + assert!(!block_writer.is_finished_below(20)); + let result = block_writer.write_block(3, &random_bytes[40..60]); + assert!( + matches!(result, Err(StorageError::ExpectedBlock(_))), + "{:?}", + result + ); + let result = block_writer.write_block(6, &random_bytes[100..102]); + assert!( + matches!(result, Err(StorageError::CapacityReached)), + "{:?}", + result + ); + assert!(!block_writer.is_finished_below(20)); + + for i in 2..6_usize { + let (l, last_in_window) = block_writer + .write_block(i as u16, &random_bytes[i * 10..2 * i * 10]) + .unwrap(); + assert_eq!(s, 20); + if i % 3 == 0 { + assert!(last_in_window); + } else { + assert!(!last_in_window); + } + assert!(!block_writer.is_finished_below(20)); + } + + let (s, last_in_windown) = block_writer + .write_block(6, &random_bytes[100..102]) + .unwrap(); + assert_eq!(s, 2); + assert!(last_in_windown); + assert!(block_writer.is_finished_below(20)); + } + + #[test] + fn test_block_write_window_size_1_packet() { + let random_bytes: Vec = (0..102).map(|_| rand::random::()).collect(); + let cursor = Arc::new(Mutex::new(Cursor::new(vec![]))); + let writer = CursorWriter { + cursor: cursor.clone(), + }; + let mut block_writer = FileWriter::from_writer(writer, 20, 0, 3); + let (s, last_in_windown) = block_writer.write_block(1, &random_bytes[..16]).unwrap(); + assert_eq!(s, 16); + assert!(!last_in_windown); + assert!(block_writer.is_finished_below(20)); + } + + #[test] + fn test_block_read() { + let random_bytes: Vec = (0..100).map(|_| rand::random::()).collect(); + let inner_reader = Cursor::new(random_bytes.clone()); + #[cfg(not(feature = "std"))] + let inner_reader = CursorReader { + cursor: inner_reader, + }; + let mut block_reader = FileReader::from_reader( + inner_reader, + 2, + 20, + Duration::from_millis(100), + instant_callback, + 1, + ); + + //can read upto maximum blocks + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 1); + assert_eq!(&block.data, &random_bytes[0..20]); + sleep(Duration::from_millis(20)); + let result = block_reader.next().unwrap(); + assert_eq!(result.unwrap().block, 2); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + + // retry reading last blocks + sleep(Duration::from_millis(101)); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 1); + assert_eq!(&block.data, &random_bytes[0..20]); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 2); + assert_eq!(&block.data, &random_bytes[20..40]); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + + // can read more blocks after free + let size = block_reader.free_block(1); + assert_eq!(size, 20); + let result = block_reader.next().unwrap(); + assert_eq!(result.unwrap().block, 3); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + + let size = block_reader.free_block(2); + assert_eq!(size, 20); + let size = block_reader.free_block(3); + assert_eq!(size, 20); + let size = block_reader.free_block(4); + assert_eq!(size, 0); + let result = block_reader.next().unwrap(); + assert_eq!(result.unwrap().block, 4); + let result = block_reader.next().unwrap(); + assert_eq!(result.unwrap().block, 5); + let size = block_reader.free_block(5); + assert_eq!(size, 20); + + // last block is empty + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 6); + assert_eq!(block.data, []); + let block = block_reader.next().unwrap(); + assert!(block.is_none()); + let size = block_reader.free_block(6); + assert_eq!(size, 0); + + // its not finished until all blocks are freed + assert!(!block_reader.is_finished(), "{:?}", block_reader); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + + let size = block_reader.free_block(4); + assert_eq!(size, 20); + assert!(block_reader.is_finished(), "{:?}", block_reader); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + } + + #[test] + fn test_block_read_window_size() { + let random_bytes: Vec = (0..100).map(|_| rand::random::()).collect(); + let inner_reader = Cursor::new(random_bytes.clone()); + #[cfg(not(feature = "std"))] + let inner_reader = CursorReader { + cursor: inner_reader, + }; + let mut block_reader = FileReader::from_reader( + inner_reader, + 2, + 20, + Duration::from_millis(100), + instant_callback, + 4, + ); + + let size = block_reader.free_block(1); + assert_eq!(size, 0); + let size = block_reader.free_block(1000); + assert_eq!(size, 0); + + // can free first block + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 1); + let size = block_reader.free_block(0); + assert_eq!(size, 0); + let size = block_reader.free_block(1); + assert_eq!(size, 20); + + // can free multiple blocks which are less than a windown size + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 2); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 3); + let size = block_reader.free_block(3); + assert_eq!(size, 40); + + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 4); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 5); + let size = block_reader.free_block(6); + assert_eq!(size, 0); + let size = block_reader.free_block(5); + assert_eq!(size, 40); + assert!(!block_reader.is_finished(), "{:?}", block_reader); + + // free last empty block + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 6); + assert_eq!(block.data, []); + assert!(!block_reader.is_finished(), "{:?}", block_reader); + let block = block_reader.next().unwrap(); + assert!(block.is_none()); + let size = block_reader.free_block(6); + assert_eq!(size, 0); + assert!(block_reader.is_finished(), "{:?}", block_reader); + let block = block_reader.next().unwrap(); + assert!(block.is_none()); + } + + #[test] + fn test_block_read_window_size_full() { + let random_bytes: Vec = (0..100).map(|_| rand::random::()).collect(); + let inner_reader = Cursor::new(random_bytes.clone()); + #[cfg(not(feature = "std"))] + let inner_reader = CursorReader { + cursor: inner_reader, + }; + let mut block_reader = FileReader::from_reader( + inner_reader, + 2, + 20, + Duration::from_millis(100), + instant_callback, + 3, + ); + + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 1); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 2); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 3); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + + let size = block_reader.free_block(3); + assert_eq!(size, 60); + + assert!(!block_reader.is_finished(), "{:?}", block_reader); + + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 4); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 5); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 6); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + + // read window again after timeout + sleep(Duration::from_millis(101)); + + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 4); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 5); + let block = block_reader.next().unwrap().unwrap(); + assert_eq!(block.block, 6); + let result = block_reader.next().unwrap(); + assert!(result.is_none()); + assert!(!block_reader.is_finished(), "{:?}", block_reader); + + let size = block_reader.free_block(3); + assert_eq!(size, 0, "{:?}", block_reader); + let size = block_reader.free_block(4); + assert_eq!(size, 20, "{:?}", block_reader); + let result = block_reader.next().unwrap(); + assert!(result.is_none(), "{:?}", block_reader); + + let size = block_reader.free_block(6); + assert_eq!(size, 20, "{:?}", block_reader); + assert!(block_reader.is_finished(), "{:?}", block_reader); + } + + #[test] + fn test_block_mapper() { + let mut mapper = BlockMapper::new(); + assert_eq!(0, mapper.block(0)); + assert_eq!(10000, mapper.block(10000)); + assert_eq!(0, mapper.index(0)); + assert_eq!(10000, mapper.index(10000)); + // rollover to next part start + assert_eq!(u16::MAX as u64, mapper.index(u16::MAX)); + assert_eq!((u16::MAX - 2) as u64, mapper.index(u16::MAX - 2)); + assert_eq!(u16::MAX as u64 + 1, mapper.index(0)); + assert_eq!(u16::MAX as u64 + 3, mapper.index(2)); + + assert_eq!(2, mapper.block(2)); + assert_eq!(u16::MAX, mapper.block(u16::MAX as u64)); + assert_eq!(0, mapper.block(u16::MAX as u64 + 1)); + + // rollover finished + assert_eq!(u16::MAX as u64 + 10001, mapper.index(10000)); + assert_eq!(u16::MAX as u64 + 10002, mapper.index(10001)); + assert_eq!(9999, mapper.block(u16::MAX as u64 + 10000)); + + // rollover to next part start + assert_eq!( + u16::MAX as u64 + u16::MAX as u64 - 9998, + mapper.index(u16::MAX - 9999) + ); + + assert_eq!(2 * (u16::MAX as u64) + 2, mapper.index(0)); + assert_eq!(2 * (u16::MAX as u64) + 3, mapper.index(1)); + + assert_eq!(65534, mapper.block(2 * (u16::MAX as u64))); + assert_eq!(65535, mapper.block(2 * (u16::MAX as u64) + 1)); + assert_eq!(0, mapper.block(2 * (u16::MAX as u64) + 2)); + assert_eq!(1998, mapper.block(2 * (u16::MAX as u64) + 2000)); + assert_eq!(9997, mapper.block(2 * (u16::MAX as u64) + 9999)); + } + + #[cfg(not(feature = "std"))] + #[derive(Debug)] + struct CursorReader { + cursor: Cursor>, + } + #[cfg(not(feature = "std"))] + impl Read for CursorReader { + fn read(&mut self, buf: &mut [u8]) -> crate::std_compat::io::Result { + use std::io::Read; + self.cursor.read(buf).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::Other) + }) + } + } + + #[cfg(not(feature = "std"))] + impl Seek for CursorReader { + fn seek(&mut self, pos: SeekFrom) -> crate::std_compat::io::Result { + use std::io::Seek; + let pos = match pos { + SeekFrom::Start(p) => std::io::SeekFrom::Start(p), + SeekFrom::Current(p) => std::io::SeekFrom::Current(p), + SeekFrom::End(p) => std::io::SeekFrom::End(p), + }; + self.cursor.seek(pos).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::Other) + }) + } + } + + #[derive(Debug)] + struct CursorWriter { + cursor: Arc>>>, + } + impl Write for CursorWriter { + fn write(&mut self, buf: &[u8]) -> crate::std_compat::io::Result { + use std::io::Write; + self.cursor.lock().unwrap().write(buf).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::Other) + }) + } + fn write_fmt(&mut self, _: core::fmt::Arguments<'_>) -> crate::std_compat::io::Result<()> { + todo!() + } + + fn flush(&mut self) -> crate::std_compat::io::Result<()> { + Ok(()) + } + } + + impl Seek for CursorWriter { + fn seek(&mut self, pos: SeekFrom) -> crate::std_compat::io::Result { + use std::io::Seek; + let pos = match pos { + SeekFrom::Start(p) => std::io::SeekFrom::Start(p), + SeekFrom::Current(p) => std::io::SeekFrom::Current(p), + SeekFrom::End(p) => std::io::SeekFrom::End(p), + }; + self.cursor.lock().unwrap().seek(pos).map_err(|_| { + crate::std_compat::io::Error::from(crate::std_compat::io::ErrorKind::Other) + }) + } + } + + fn instant_callback() -> Instant { + #[cfg(feature = "std")] + return std::time::Instant::now(); + #[cfg(not(feature = "std"))] + Instant::from_time(|| { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Time went backwards") + .as_micros() as u64 + }) + } +} diff --git a/stat b/stat new file mode 100755 index 0000000..5afa686 --- /dev/null +++ b/stat @@ -0,0 +1,316 @@ +#!/bin/bash + +set -eEux -o pipefail + +TEST_DIR="./target/tftp-232342" +OUTPUT_DIR="./target/info" + +mkdir -p ./target/info + +server_heap() { + local server="$1" + local client="$2" + rm -f target/server_file + head -c 10M /dev/urandom > target/client_file + ( sleep 5 ; $client send 127.0.0.1:9000 target/client_file --remote-path server_file )& + valgrind --tool=massif --massif-out-file=target/massif.out $server server 127.0.0.1:9000 ./target +} + +server_flamegraph() { + local server="$1" + local client="$2" + local suffix="${3:-""}" + rm -f target/server_file + head -c 10M /dev/urandom > target/client_file + (sleep 5 ; $client send 127.0.0.1:9000 target/client_file --remote-path server_file ; killall $server)& + flamegraph -o $OUTPUT_DIR/server_flamegraph${suffix}.svg -- $server server 127.0.0.1:9000 ./target/ +} + +send_flamegraph() { + local server="$1" + local client="$2" + local suffix="${3:-""}" + local server_pids=() + rm -f target/server_file + head -c 10M /dev/urandom > target/send_file + $server server 127.0.0.1:9000 ./target/ & server_pids+=($!) + flamegraph -o $OUTPUT_DIR/send_flamegraph${suffix}.svg -- $client send 127.0.0.1:9000 target/send_file --remote-path server_file + kill "${server_pids[@]}" +} + +receive_flamegraph() { + local server="$1" + local client="$2" + local suffix="${3:-""}" + local server_pids=() + rm -f target/server_file + head -c 10M /dev/urandom > target/server_file + $server server 127.0.0.1:9000 ./target/ & server_pids+=($!) + flamegraph -o $OUTPUT_DIR/receive_flamegraph${suffix}.svg -- $client receive 127.0.0.1:9000 server_file --local-path target/receive_file + kill "${server_pids[@]}" +} + +send_dump() { + local server="$1" + local client="$2" + local suffix="${3:-""}" + local server_pids=() + local dump_pids=() + rm -f target/server_file + head -c 1M /dev/urandom > target/send_file + sudo -v + sudo tcpdump -s 65535 -i lo -w $OUTPUT_DIR/send_capture${suffix}.pcap port 9000 & dump_pids+=($!) + sleep 1 + $server server 127.0.0.1:9000 ./target/ & server_pids+=($!) + $client send 127.0.0.1:9000 target/send_file --remote-path server_file + sleep 1 + kill "${server_pids[@]}" + sudo kill "`ps -C keyword -o pid= --ppid ${dump_pids[@]}`" +} + +receive_dump() { + local server="$1" + local client="$2" + local suffix="${3:-""}" + local server_pids=() + local dump_pids=() + + rm -f target/server_file + head -c 1M /dev/urandom > target/server_file + sudo -v + sudo tcpdump -s 65535 -i lo -w $OUTPUT_DIR/receive_capture${suffix}.pcap port 9000 & dump_pids+=($!) + sleep 1 + $server server 127.0.0.1:9000 ./target/ & server_pids+=($!) + $client receive 127.0.0.1:9000 server_file --local-path target/receive_file + sleep 1 + kill "${server_pids[@]}" + sudo kill "`ps -C keyword -o pid= --ppid ${dump_pids[@]}`" +} + +send_receive_full_encryption_dump() { + local server="$1" + local client="$2" + local private_key="tn4oZ8Rtgci2CNULF7UYdgeKz0i+jiK0O2Gs0PPjZk8=" + local public_key="uNzZDPe9sRhuXRTAM8YjCSmt7OHhlBahKCPOarNwCk0=" + local server_pids=() + local dump_pids=() + rm -f target/server_file + head -c 1M /dev/urandom > target/send_file + sudo -v + sudo tcpdump -s 65535 -i lo -w $OUTPUT_DIR/full_encryption_capture.pcap port 9000 & dump_pids+=($!) + sleep 1 + $server server 127.0.0.1:9000 ./target/ --private-key $private_key --required-full-encryption true & server_pids+=($!) + $client send 127.0.0.1:9000 target/send_file --remote-path server_file --encryption-level protocol --server-public-key $public_key + $client receive 127.0.0.1:9000 server_file --local-path target/receive_file --encryption-level protocol --server-public-key $public_key + sleep 1 + kill "${server_pids[@]}" + sudo kill "`ps -C keyword -o pid= --ppid ${dump_pids[@]}`" +} + +measure_localhost_window_size() { + local server="$1" + local client="$2" + local suffix="${3:-""}" + local sender_data="$OUTPUT_DIR/sender_window_localhost$suffix" + local receiver_data="$OUTPUT_DIR/receiver_window_localhost$suffix" + local server_pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + > $sender_data + > $receiver_data + + head -c 100M /dev/urandom > $TEST_DIR/client/samples/100M + $server server 127.0.0.1:9000 $TEST_DIR/server --max-file-size 104857600 --allow-overwrite & server_pids+=($!) + + for window_size in 1 2 4 6 8 10 12 14 16 32 64; do + /usr/bin/time -o $sender_data -a -f "$window_size %e %M %K" $client send 127.0.0.1:9000 $TEST_DIR/client/samples/100M --remote-path samples/100M --window-size $window_size + /usr/bin/time -o $receiver_data -a -f "$window_size %e %M %K" $client receive 127.0.0.1:9000 samples/100M --max-file-size 104857600 --window-size $window_size --local-path $TEST_DIR/client/samples/100M + done + + kill "${server_pids[@]}" + + plot_window_size $sender_data $receiver_data + plot_window_size_image $sender_data $receiver_data $suffix +} + +measure_localhost_queue_size() { + local server="$1" + local client="$2" + local sender_data="$OUTPUT_DIR/sender_queue_localhost" + local receiver_data="$OUTPUT_DIR/receiver_queue_localhost" + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + > $sender_data + > $receiver_data + + head -c 100M /dev/urandom > $TEST_DIR/client/samples/100M + + for queue_size in 1 2 4 8 16 32 64 128 256 512 1000; do + local server_pids=() + $server server 127.0.0.1:9000 $TEST_DIR/server --max-file-size 104857600 --allow-overwrite --max-blocks-in-queue-reader $queue_size --max-blocks-in-queue-writer $queue_size & server_pids+=($!) + /usr/bin/time -o $sender_data -a -f "$queue_size %e %M %K" $client send 127.0.0.1:9000 $TEST_DIR/client/samples/100M --remote-path samples/100M --window-size 1 --max-blocks-in-queue $queue_size + /usr/bin/time -o $receiver_data -a -f "$queue_size %e %M %K" $client receive 127.0.0.1:9000 samples/100M --max-file-size 104857600 --window-size 1 --max-blocks-in-queue $queue_size --local-path $TEST_DIR/client/samples/100M + kill "${server_pids[@]}" + sleep 1 + done + + plot_queue_size $sender_data $receiver_data +} + +measure_endpoint_window_size() { + local client="$1" + local endpoint="$2" + local suffix="${3:-""}" + local sender_data="$OUTPUT_DIR/sender_window_$endpoint$suffix" + local receiver_data="$OUTPUT_DIR/receiver_window_$endpoint$suffix" + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + > $sender_data + > $receiver_data + + head -c 100M /dev/urandom > $TEST_DIR/client/samples/100M + + for window_size in 1 2 4 6 8 10 12 14 16 32 64; do + /usr/bin/time -o $sender_data -a -f "$window_size %e %M %K" $client send $endpoint $TEST_DIR/client/samples/100M --remote-path samples/100M --window-size $window_size + /usr/bin/time -o $receiver_data -a -f "$window_size %e %M %K" $client receive $endpoint samples/100M --max-file-size 104857600 --window-size $window_size --local-path $TEST_DIR/client/samples/100M + done + + plot_window_size $sender_data $receiver_data + plot_window_size_image $sender_data $receiver_data $suffix +} + +plot_window_size() { + local sender_data="$1" + local receiver_data="$2" + + gnuplot -p < $TEST_DIR/authorized + head -c 10K /dev/urandom > $TEST_DIR/client/file + + $server server 127.0.0.1:9000 $TEST_DIR/server -a --max-blocks-in-queue-reader 4 --max-blocks-in-queue-writer 4 --request-timeout 10000 \ + --max-file-size 100000000 --max-block-size 512 --authorized-keys $TEST_DIR/authorized --private-key "$private_key" & server_pids+=($!) + + time $client send 127.0.0.1:9000 $TEST_DIR/client/file --listen 127.0.0.1:0 --remote-path new-path --max-blocks-in-queue 2 --request-timeout 10000 \ + --max-file-size 100000000 --block-size 110 --encryption-level protocol --server-public-key "$public_key" --private-key "$client_private_key" \ + --known-hosts $TEST_DIR/known + + cmp -s $TEST_DIR/client/file $TEST_DIR/server/new-path + + time $client receive 127.0.0.1:9000 new-path --local-path $TEST_DIR/delete/file --listen 127.0.0.1:0 --max-blocks-in-queue 4 --request-timeout 10000 \ + --max-file-size 100000000 --block-size 120 --encryption-level protocol --private-key "$client_private_key" \ + --known-hosts $TEST_DIR/known + + cmp -s $TEST_DIR/delete/file $TEST_DIR/server/new-path + + kill "${server_pids[@]}" +} + +test_large_files() { + local server="$1" + local client="$2" + local window_size="${3:-1}" + local server_pids=() + local pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + head -c 111M /dev/urandom > $TEST_DIR/client/samples/111M + head -c 112M /dev/urandom > $TEST_DIR/server/samples/112M + + $server server 127.0.0.1:9000 $TEST_DIR/server --max-file-size 524288000 & server_pids+=($!) + time $client send 127.0.0.1:9000 $TEST_DIR/client/samples/111M --remote-path samples/111M --window-size $window_size & pids+=($!) + time $client receive 127.0.0.1:9000 samples/112M --max-file-size 724288000 --window-size $window_size --local-path $TEST_DIR/client/samples/112M & pids+=($!) + wait "${pids[@]}" + + cmp -s $TEST_DIR/client/samples/111M $TEST_DIR/server/samples/111M + cmp -s $TEST_DIR/client/samples/112M $TEST_DIR/server/samples/112M + kill "${server_pids[@]}" +} + +test_high_load() { + local server="$1" + local client="$2" + local window_size="${3:-1}" + local size=50 + local max_size=$((size + size)) + local server_pids=() + local pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + $server server 127.0.0.1:9000 $TEST_DIR/server/samples & server_pids+=($!) + + for ((i=1;i<=size;i++)); do + head -c 1M /dev/urandom > $TEST_DIR/client/samples/$i + done; + for ((i=size+1;i<=max_size;i++)); do + head -c 1M /dev/urandom > $TEST_DIR/server/samples/$i + done; + for ((i=1;i<=size;i++)); do + $client send 127.0.0.1:9000 $TEST_DIR/client/samples/$i --window-size $window_size & pids+=($!) + done + for ((i=size+1;i<=max_size;i++)); do + $client receive 127.0.0.1:9000 $i --window-size $window_size --local-path $TEST_DIR/delete/$i & pids+=($!) + done + time wait "${pids[@]}" + + for ((i=1;i<=size;i++)); do + cmp -s $TEST_DIR/client/samples/$i $TEST_DIR/server/samples/$i + done + for ((i=size+1;i<=max_size;i++)); do + cmp -s $TEST_DIR/server/samples/$i $TEST_DIR/delete/$i + done + kill "${server_pids[@]}" +} + +test_encryption_level() { + local server="$1" + local client="$2" + local data="hello" + local server_pids=() + local pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + $server server 127.0.0.1:9000 $TEST_DIR/server & pids+=($!) + + for level in data optional-data protocol optional-protocol none; do + local remote_path=$(openssl rand -hex 12) + echo "$data" | $client send 127.0.0.1:9000 /dev/stdin --remote-path $remote_path --encryption-level $level + local received=$($client receive 127.0.0.1:9000 $remote_path --local-path /dev/stdout --encryption-level $level) + if [[ "$data" != "$received" ]]; then + exit 1 + fi + done; + + kill "${pids[@]}" +} + +test_standard_tftp() { + local server="$1" + local client="$2" + local data=$(openssl rand -hex 1500) + local server_pids=() + local pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + $server server 127.0.0.1:9000 $TEST_DIR/server --require-server-port-change --max-blocks-in-queue-reader 1 --max-blocks-in-queue-writer 1 & pids+=($!) + + local remote_path=$(openssl rand -hex 12) + echo "$data" | $client send 127.0.0.1:9000 /dev/stdin --remote-path $remote_path --allow-server-port-change --window-size 1 --max-blocks-in-queue 1 + local received=$($client receive 127.0.0.1:9000 $remote_path --local-path /dev/stdout --allow-server-port-change --window-size 1 --max-blocks-in-queue 1) + if [[ "$data" != "$received" ]]; then + exit 1 + fi + + kill "${pids[@]}" +} + +test_encryption_authorized_only() { + local server="$1" + local client="$2" + local private_key="tn4oZ8Rtgci2CNULF7UYdgeKz0i+jiK0O2Gs0PPjZk8=" + local public_key="uNzZDPe9sRhuXRTAM8YjCSmt7OHhlBahKCPOarNwCk0=" + local client_private_key="ZoCtWKMLP8bPQFbOHMu9AzkVMaUIxiXhDYhQwDGlNas=" + local client_public_key="hX0vxxwVcP/uegcppn46e8maSXFduJDG1IywVYhlMmA=" + local data="hello" + local server_pids=() + local pids=() + + rm -rf "$TEST_DIR" + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + echo "$client_public_key" > $TEST_DIR/authorized + echo "127.0.0.1:9000 $public_key" > $TEST_DIR/known + head -c 10M /dev/urandom > $TEST_DIR/client/file + + $server server 127.0.0.1:9000 $TEST_DIR/server --required-full-encryption false --authorized-keys $TEST_DIR/authorized --private-key "$private_key" & server_pids+=($!) + + local remote_path=$(openssl rand -hex 12) + # disallow no public key + echo "$data" | $client send 127.0.0.1:9000 /dev/stdin --request-timeout 500 \ + --remote-path $remote_path --private-key "$client_private_key" --encryption-level none && exit 1 || true + $client receive 127.0.0.1:9000 $remote_path --local-path /dev/stdout --request-timeout 500 \ + --private-key "$client_private_key" --encryption-level none && exit 1 || true + for level in data optional-data protocol optional-protocol; do + local remote_path=$(openssl rand -hex 12) + echo "$data" | $client send 127.0.0.1:9000 /dev/stdin --request-timeout 500 \ + --remote-path $remote_path --private-key "$client_private_key" --encryption-level $level + local received=$($client receive 127.0.0.1:9000 $remote_path --local-path /dev/stdout --request-timeout 500 --private-key "$client_private_key" --encryption-level $level) + if [[ "$data" != "$received" ]]; then + exit 1 + fi + local remote_path=$(openssl rand -hex 12) + echo "$data" | $client send 127.0.0.1:9000 /dev/stdin --request-timeout 500 \ + --remote-path $remote_path --server-public-key "$public_key" --private-key "$client_private_key" --encryption-level $level + local received=$($client receive 127.0.0.1:9000 $remote_path --local-path /dev/stdout --request-timeout 500 --server-public-key "$public_key" --private-key "$client_private_key" --encryption-level $level) + if [[ "$data" != "$received" ]]; then + exit 1 + fi + local remote_path=$(openssl rand -hex 12) + echo "$data" | $client send 127.0.0.1:9000 /dev/stdin --request-timeout 500 \ + --remote-path $remote_path --known-hosts $TEST_DIR/known --private-key "$client_private_key" --encryption-level $level + local received=$($client receive 127.0.0.1:9000 $remote_path --local-path /dev/stdout --request-timeout 500 --known-hosts $TEST_DIR/known --private-key "$client_private_key" --encryption-level $level) + if [[ "$data" != "$received" ]]; then + exit 1 + fi + done; + + + kill "${server_pids[@]}" +} + +test_curl_client() { + local server="$1" + local server_pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + + head -c 100M /dev/urandom > $TEST_DIR/client/samples/100M + + $server server 127.0.0.1:9000 $TEST_DIR/server --max-file-size 104857600 & server_pids+=($!) + curl -T $TEST_DIR/client/samples/100M tftp://127.0.0.1:9000 + curl -o $TEST_DIR/delete/100M tftp://127.0.0.1:9000/100M + kill "${server_pids[@]}" +} + + +test_hpa_tftp_server() { + local client="$1" + local server_pids=() + + rm -rf $TEST_DIR + mkdir -p $TEST_DIR/{server/samples,client/samples,delete} + # --foreground --address 127.0.0.1:9000 does not work + # echo TFTPD_ARGS="--secure --create -vvv /tmp" > /etc/conf.d/tftpd + + sudo rm -f /tmp/100M + + head -c 100M /dev/urandom > $TEST_DIR/client/samples/100M + + sudo systemctl start tftpd + + $client send 127.0.0.1:69 $TEST_DIR/client/samples/100M --allow-server-port-change + $client receive 127.0.0.1:69 100M --max-file-size 104857600 --local-path $TEST_DIR/delete/100M --allow-server-port-change + + sudo systemctl stop tftpd +} + +test_bin() { + cargo test -p tftp-binary + cargo test -p tftp-binary --no-default-features --features std + cargo test -p tftp-binary --no-default-features --features alloc + cargo test -p tftp-binary --no-default-features --features encryption + cargo test -p tftp-binary --no-default-features --features std,alloc + cargo test -p tftp-binary --no-default-features --features alloc,encryption + cargo test -p tftp-binary --no-default-features --features std,encryption + cargo test -p tftp-binary --no-default-features +} + + +test_lib() { + cargo test -p tftp + cargo test -p tftp --no-default-features --features std + cargo test -p tftp --no-default-features --features alloc + cargo test -p tftp --no-default-features --features encryption + cargo test -p tftp --no-default-features --features std,alloc + cargo test -p tftp --no-default-features --features alloc,encryption + cargo test -p tftp --no-default-features --features std,encryption + cargo test -p tftp --no-default-features +} + +build_debug_targets() { + cargo build -p tftp-binary + cp ./target/debug/tftp ./target/tftp + + cargo build -p tftp-binary --no-default-features --features encryption + cp ./target/debug/tftp ./target/tftp-stack-encryption + + cargo build -p tftp-binary --no-default-features --features alloc + cp ./target/debug/tftp ./target/tftp-alloc + + cargo build -p tftp-binary --no-default-features + cp ./target/debug/tftp ./target/tftp-stack +} + +test_all() { + local encryption_targets=(./target/tftp ./target/tftp-stack-encryption) + local non_encryption_targets=(./target/tftp-alloc ./target/tftp-stack) + + build_debug_targets + + test_lib + test_bin + for server in ${encryption_targets[@]}; do + for client in ${encryption_targets[@]}; do + test_full_config $server $client + test_large_files $server $client 1 + test_large_files $server $client 4 + test_high_load $server $client 1 + test_high_load $server $client 4 + test_encryption_level $server $client + test_encryption_authorized_only $server $client + test_standard_tftp $server $client + done + done + + for server in ${non_encryption_targets[@]}; do + for client in ${non_encryption_targets[@]}; do + test_large_files $server $client 4 + test_high_load $server $client 4 + test_standard_tftp $server $client + done + done + + # non encryption server communication with encrypted clients + for server in ${non_encryption_targets[@]}; do + for client in ${encryption_targets[@]}; do + test_encryption_level $server $client + test_standard_tftp $server $client + done + done +} + +$1 "${2:-""}" "${3:-""}" "${4:-""}"