mirror of
https://gitee.com/fantix/kloop.git
synced 2024-11-21 18:01:00 +00:00
WIP resolver
This commit is contained in:
parent
3b4b6c5c67
commit
dd4a38a610
22 changed files with 1900 additions and 45 deletions
|
@ -1,5 +1,8 @@
|
|||
include Makefile
|
||||
include architecture.png
|
||||
recursive-include src *.pyx *.pxd *.h
|
||||
include resolver/Cargo.toml
|
||||
include resolver/Cargo.lock
|
||||
recursive-include resolver *.rs
|
||||
graft tests
|
||||
global-exclude *.py[cod] *.c
|
||||
|
|
701
resolver/Cargo.lock
generated
Normal file
701
resolver/Cargo.lock
generated
Normal file
|
@ -0,0 +1,701 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-macro",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"match_cfg",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipconfig"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"widestring",
|
||||
"winapi",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.124"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru-cache"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "match_cfg"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
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",
|
||||
]
|
||||
|
||||
[[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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolver"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"libc",
|
||||
"log",
|
||||
"resolv-conf",
|
||||
"trust-dns-proto",
|
||||
"trust-dns-resolver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f48b6d60512a392e34dbf7fd456249fd2de3c83669ab642e021903f4015185b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.21.2"
|
||||
source = "git+https://github.com/fantix/trust-dns?branch=0_21_2_patch#843c22f1d267660d816480d7168c17ee5467cda8"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"cfg-if",
|
||||
"data-encoding",
|
||||
"enum-as-inner",
|
||||
"futures-channel",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"idna",
|
||||
"ipnet",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rand",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tinyvec",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-resolver"
|
||||
version = "0.21.2"
|
||||
source = "git+https://github.com/fantix/trust-dns?branch=0_21_2_patch#843c22f1d267660d816480d7168c17ee5467cda8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"ipconfig",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"lru-cache",
|
||||
"parking_lot",
|
||||
"resolv-conf",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"matches",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
19
resolver/Cargo.toml
Normal file
19
resolver/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "resolver"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "kloop_resolver"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.124"
|
||||
log = "0.4.16"
|
||||
resolv-conf = { version = "0.7.0", features = ["system"] }
|
||||
trust-dns-proto = { git = "https://github.com/fantix/trust-dns", branch = "0_21_2_patch", default-features = true }
|
||||
trust-dns-resolver = { git = "https://github.com/fantix/trust-dns", branch = "0_21_2_patch", default-features = true }
|
||||
futures-util = "0.3.21"
|
||||
futures-io = "0.3.5"
|
||||
futures-executor = "0.3.5"
|
||||
async-trait = "0.1.43"
|
53
resolver/src/kloop.rs
Normal file
53
resolver/src/kloop.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
kLoop is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
|
||||
use core::marker;
|
||||
use std::task::Waker;
|
||||
use libc;
|
||||
|
||||
use crate::resolve::KLoopResolver;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CResolver {
|
||||
_data: [u8; 0],
|
||||
_marker: marker::PhantomData<(*mut u8, marker::PhantomPinned)>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CResolve {
|
||||
_data: [u8; 0],
|
||||
_marker: marker::PhantomData<(*mut u8, marker::PhantomPinned)>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct UDPSend {
|
||||
_data: [u8; 0],
|
||||
_marker: marker::PhantomData<(*mut u8, marker::PhantomPinned)>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn resolver_set(c_resolver: *const CResolver, resolver: *mut KLoopResolver);
|
||||
// pub fn resolve_set_poller(resolve: *const CResolve, poller: *mut Poller);
|
||||
pub fn resolve_prep_addr(resolve: *const CResolve) -> *mut libc::sockaddr;
|
||||
pub fn resolve_done_cb(resolve: *const CResolve) -> libc::c_int;
|
||||
pub fn udp_bind(addr: *const libc::sockaddr, addrlen: libc::socklen_t) -> libc::c_int;
|
||||
pub fn udp_send_init(fd: libc::c_int, resolver: *const CResolver) -> libc::c_ulong;
|
||||
pub fn udp_send_poll(
|
||||
send: libc::c_ulong,
|
||||
data: *const u8,
|
||||
datalen: libc::size_t,
|
||||
addr: *const libc::sockaddr,
|
||||
addrlen: libc::socklen_t,
|
||||
waker: *mut Waker,
|
||||
) -> libc::c_int;
|
||||
}
|
18
resolver/src/lib.rs
Normal file
18
resolver/src/lib.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
kLoop is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
|
||||
mod kloop;
|
||||
mod resolve;
|
||||
mod runtime;
|
||||
|
||||
pub use resolve::{resolver_init, resolver_lookup_ip};
|
57
resolver/src/poller.rs
Normal file
57
resolver/src/poller.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use futures_util::task::noop_waker_ref;
|
||||
|
||||
use libc;
|
||||
|
||||
pub type BoxFuture<'a, T> = Box<dyn Future<Output = T> + 'a>;
|
||||
|
||||
pub struct Poller<'a> {
|
||||
ctx: Context<'a>,
|
||||
fut: BoxFuture<'a, libc::c_int>,
|
||||
}
|
||||
|
||||
impl<'a> Poller<'a> {
|
||||
pub fn new(fut: impl Future<Output = libc::c_int> + 'a) -> Self {
|
||||
let waker = noop_waker_ref();
|
||||
Poller {
|
||||
ctx: Context::from_waker(waker),
|
||||
fut: Box::new(fut),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(&mut self) -> Option<libc::c_int> {
|
||||
let fut = unsafe { Pin::new_unchecked(self.fut.as_mut()) };
|
||||
match fut.poll(&mut self.ctx) {
|
||||
Poll::Ready(rv) => Some(rv),
|
||||
Poll::Pending => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OnceFuture {
|
||||
seen: bool,
|
||||
}
|
||||
|
||||
impl OnceFuture {
|
||||
pub fn new() -> Self {
|
||||
Self { seen: false }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Future for OnceFuture {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.seen {
|
||||
println!("poll ready");
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
println!("poll pending");
|
||||
self.get_mut().seen = true;
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
185
resolver/src/resolve.rs
Normal file
185
resolver/src/resolve.rs
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
kLoop is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
|
||||
use futures_executor::{LocalPool, LocalSpawner};
|
||||
use futures_util::task::{LocalSpawnExt, SpawnError};
|
||||
use std;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::net::IpAddr;
|
||||
use std::rc::Rc;
|
||||
|
||||
use libc;
|
||||
use trust_dns_resolver::name_server::{GenericConnection, GenericConnectionProvider};
|
||||
use trust_dns_resolver::system_conf::parse_resolv_conf;
|
||||
use trust_dns_resolver::{AsyncResolver, Hosts};
|
||||
|
||||
use crate::kloop::{resolve_done_cb, resolve_prep_addr, resolver_set, CResolve, CResolver};
|
||||
use crate::runtime::{KLoopHandle, KLoopRuntime};
|
||||
|
||||
const DEFAULT_PORT: u16 = 53;
|
||||
|
||||
type KLoopConnection = GenericConnection;
|
||||
|
||||
type KLoopConnectionProvider = GenericConnectionProvider<KLoopRuntime>;
|
||||
|
||||
thread_local! {
|
||||
pub static CURRENT_RESOLVER: Rc<RefCell<Option<*mut KLoopResolver>>> = Rc::new(RefCell::new(None));
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KLoopResolver {
|
||||
resolver: AsyncResolver<KLoopConnection, KLoopConnectionProvider>,
|
||||
pub c_resolver: *const CResolver,
|
||||
pool: LocalPool,
|
||||
spawner: LocalSpawner,
|
||||
}
|
||||
|
||||
impl KLoopResolver {
|
||||
fn new(
|
||||
resolv_conf: &[u8],
|
||||
hosts_conf: &[u8],
|
||||
c_resolver: *const CResolver,
|
||||
) -> io::Result<Self> {
|
||||
let (config, mut options) = parse_resolv_conf(resolv_conf)?;
|
||||
options.use_hosts_file = false;
|
||||
let conn_provider = GenericConnectionProvider::new(KLoopHandle);
|
||||
let mut resolver = AsyncResolver::new_with_conn(config, options, conn_provider).unwrap();
|
||||
resolver.set_hosts(Some(Hosts::default().read_hosts_conf(hosts_conf)));
|
||||
let pool = LocalPool::new();
|
||||
let spawner = pool.spawner();
|
||||
Ok(Self {
|
||||
resolver,
|
||||
c_resolver,
|
||||
pool,
|
||||
spawner,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError>
|
||||
where
|
||||
Fut: Future<Output = ()> + 'static,
|
||||
{
|
||||
self.spawner.spawn_local(future)
|
||||
}
|
||||
|
||||
fn run_until_stalled(&mut self) {
|
||||
loop {
|
||||
self.pool.run_until_stalled();
|
||||
if !self.pool.try_run_one() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn lookup_ip(&self, resolve: *mut CResolve, host: &str, port: libc::in_port_t) -> () {
|
||||
match self.resolver.lookup_ip(host).await {
|
||||
Ok(result) => {
|
||||
for ip in result.into_iter() {
|
||||
match ip {
|
||||
IpAddr::V4(ip) => unsafe {
|
||||
let out = resolve_prep_addr(resolve) as *mut libc::sockaddr_in;
|
||||
if out.is_null() {
|
||||
println!("resolve_prep_addr returned NULL");
|
||||
break;
|
||||
}
|
||||
(*out).sin_family = libc::AF_INET as libc::sa_family_t;
|
||||
(*out).sin_addr = libc::in_addr {
|
||||
s_addr: u32::from_ne_bytes(ip.octets()),
|
||||
};
|
||||
(*out).sin_port = port.to_be();
|
||||
(*out).sin_zero = [0; 8];
|
||||
},
|
||||
IpAddr::V6(ip) => unsafe {
|
||||
let out = resolve_prep_addr(resolve) as *mut libc::sockaddr_in6;
|
||||
if out.is_null() {
|
||||
println!("resolve_prep_addr returned NULL");
|
||||
break;
|
||||
}
|
||||
(*out).sin6_family = libc::AF_INET6 as libc::sa_family_t;
|
||||
(*out).sin6_addr = libc::in6_addr {
|
||||
s6_addr: ip.octets(),
|
||||
};
|
||||
(*out).sin6_port = port.to_be();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("lookup_ip error: {:?}", e);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
resolve_done_cb(resolve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn resolver_init(
|
||||
c_resolver: *const CResolver,
|
||||
resolv_conf_data: *const u8,
|
||||
resolv_conf_data_size: libc::size_t,
|
||||
hosts_conf_data: *const u8,
|
||||
hosts_conf_data_size: libc::size_t,
|
||||
) -> libc::c_int {
|
||||
let resolv_conf =
|
||||
unsafe { std::slice::from_raw_parts(resolv_conf_data, resolv_conf_data_size) };
|
||||
let hosts_conf = unsafe { std::slice::from_raw_parts(hosts_conf_data, hosts_conf_data_size) };
|
||||
let mut resolver = match KLoopResolver::new(resolv_conf, hosts_conf, c_resolver) {
|
||||
Ok(resolver) => resolver,
|
||||
Err(e) => return 0,
|
||||
};
|
||||
let rv = Box::into_raw(Box::new(resolver));
|
||||
unsafe {
|
||||
resolver_set(c_resolver, rv);
|
||||
}
|
||||
1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn resolver_lookup_ip(
|
||||
resolver: *mut KLoopResolver,
|
||||
resolve: *mut CResolve,
|
||||
host_raw: *const u8,
|
||||
length: libc::size_t,
|
||||
port: libc::in_port_t,
|
||||
) -> libc::c_int {
|
||||
let host = match std::str::from_utf8(unsafe { std::slice::from_raw_parts(host_raw, length) }) {
|
||||
Ok(host) => host,
|
||||
_ => return 0,
|
||||
};
|
||||
let r = || unsafe { resolver.as_mut() }.unwrap();
|
||||
|
||||
let fut = r().lookup_ip(resolve, host, port);
|
||||
if let Err(e) = r().spawn(fut) {
|
||||
println!("spawn error: {:?}", e);
|
||||
return 0;
|
||||
}
|
||||
CURRENT_RESOLVER.with(|current| {
|
||||
*current.borrow_mut() = Some(resolver);
|
||||
r().run_until_stalled();
|
||||
*current.borrow_mut() = None;
|
||||
});
|
||||
1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn resolver_run_until_stalled(resolver: *mut KLoopResolver) {
|
||||
CURRENT_RESOLVER.with(|current| {
|
||||
*current.borrow_mut() = Some(resolver);
|
||||
unsafe { resolver.as_mut() }.unwrap().run_until_stalled();
|
||||
*current.borrow_mut() = None;
|
||||
});
|
||||
}
|
209
resolver/src/runtime.rs
Normal file
209
resolver/src/runtime.rs
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
kLoop is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
|
||||
use crate::kloop;
|
||||
use crate::resolve::CURRENT_RESOLVER;
|
||||
use async_trait::async_trait;
|
||||
use futures_io::{AsyncRead, AsyncWrite};
|
||||
use libc::{sockaddr, socklen_t};
|
||||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::net::SocketAddr;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
use std::time::Duration;
|
||||
use std::{io, mem};
|
||||
use trust_dns_proto::error::ProtoError;
|
||||
use trust_dns_proto::tcp::{Connect, DnsTcpStream};
|
||||
use trust_dns_proto::udp::UdpSocket;
|
||||
use trust_dns_proto::Time;
|
||||
use trust_dns_resolver::name_server::{RuntimeProvider, Spawn};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct KLoopTimer {}
|
||||
|
||||
#[async_trait]
|
||||
impl Time for KLoopTimer {
|
||||
async fn delay_for(duration: Duration) {
|
||||
println!("TODO: delay_for: {:?}", duration);
|
||||
}
|
||||
|
||||
async fn timeout<F: 'static + Future + Send>(
|
||||
duration: Duration,
|
||||
future: F,
|
||||
) -> io::Result<F::Output> {
|
||||
println!("TODO: timeout: {:?}", duration);
|
||||
Ok(future.await)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KLoopTcp {}
|
||||
|
||||
#[async_trait]
|
||||
impl Connect for KLoopTcp {
|
||||
async fn connect_with_bind(
|
||||
addr: SocketAddr,
|
||||
bind_addr: Option<SocketAddr>,
|
||||
) -> io::Result<Self> {
|
||||
println!("TODO: connect_with_bind: {:?} {:?}", addr, bind_addr);
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for KLoopTcp {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
println!("TODO: poll_read");
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for KLoopTcp {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
println!("TODO: poll_write");
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
println!("TODO: poll_flush");
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
println!("TODO: poll_close");
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl DnsTcpStream for KLoopTcp {
|
||||
type Time = KLoopTimer;
|
||||
}
|
||||
|
||||
pub struct KLoopUdp {
|
||||
fd: libc::c_int,
|
||||
send: libc::c_ulong,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl UdpSocket for KLoopUdp {
|
||||
type Time = KLoopTimer;
|
||||
|
||||
async fn bind(addr: SocketAddr) -> io::Result<Self> {
|
||||
let (addr_ptr, addr_len) = socket_addr_as_ptr(addr);
|
||||
let fd = unsafe { kloop::udp_bind(addr_ptr, addr_len) };
|
||||
CURRENT_RESOLVER.with(|resolver| {
|
||||
let resolver = resolver.borrow().unwrap();
|
||||
let resolver = unsafe { resolver.as_ref() }.unwrap();
|
||||
let resolver = resolver.c_resolver;
|
||||
let send = unsafe { kloop::udp_send_init(fd, resolver) };
|
||||
Ok(KLoopUdp { fd, send })
|
||||
})
|
||||
}
|
||||
|
||||
fn poll_recv_from(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<(usize, SocketAddr)>> {
|
||||
println!("TODO: poll_recv_from");
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn poll_send_to(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
target: SocketAddr,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let waker = Box::new(cx.waker().clone());
|
||||
let (addr, addrlen) = socket_addr_as_ptr(target);
|
||||
match unsafe {
|
||||
kloop::udp_send_poll(
|
||||
self.send,
|
||||
buf.as_ptr(),
|
||||
buf.len(),
|
||||
addr,
|
||||
addrlen,
|
||||
Box::into_raw(waker),
|
||||
)
|
||||
} {
|
||||
res if res > 0 => {
|
||||
Poll::Ready(Ok(res as usize))
|
||||
}
|
||||
res => {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn socket_addr_as_ptr(addr: SocketAddr) -> (*const sockaddr, socklen_t) {
|
||||
match addr {
|
||||
SocketAddr::V4(ref a) => (
|
||||
a as *const _ as *const _,
|
||||
mem::size_of_val(a) as libc::socklen_t,
|
||||
),
|
||||
SocketAddr::V6(ref a) => (
|
||||
a as *const _ as *const _,
|
||||
mem::size_of_val(a) as libc::socklen_t,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct KLoopHandle;
|
||||
|
||||
impl Spawn for KLoopHandle {
|
||||
fn spawn_bg<F>(&mut self, future: F)
|
||||
where
|
||||
F: Future<Output = Result<(), ProtoError>> + Send + 'static,
|
||||
{
|
||||
CURRENT_RESOLVER.with(|resolver| {
|
||||
let r = resolver.borrow().unwrap();
|
||||
let r = unsafe { r.as_mut() }.unwrap();
|
||||
r.spawn(async {
|
||||
future.await.unwrap_or_else(|e| {
|
||||
println!("spawn_bg error: {:?}", e);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct KLoopRuntime;
|
||||
|
||||
impl RuntimeProvider for KLoopRuntime {
|
||||
type Handle = KLoopHandle;
|
||||
type Timer = KLoopTimer;
|
||||
type Udp = KLoopUdp;
|
||||
type Tcp = KLoopTcp;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn waker_wake(waker: *mut Waker) {
|
||||
let waker = unsafe { Box::from_raw(waker) };
|
||||
waker.wake();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn waker_forget(waker: *mut Waker) {
|
||||
unsafe { Box::from_raw(waker) };
|
||||
}
|
29
setup.py
29
setup.py
|
@ -9,17 +9,42 @@
|
|||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
import subprocess
|
||||
import sysconfig
|
||||
|
||||
from setuptools import setup
|
||||
from Cython.Build import cythonize
|
||||
from Cython.Distutils import Extension
|
||||
from Cython.Distutils import build_ext
|
||||
|
||||
|
||||
DEBUG = True
|
||||
RESOLVER_LIB = (
|
||||
f"resolver/target/{'debug' if DEBUG else 'release'}/libkloop_resolver.a"
|
||||
)
|
||||
|
||||
|
||||
class build_ext_with_resolver(build_ext):
|
||||
def run(self):
|
||||
subprocess.check_call(
|
||||
["cargo", "build"] + [] if DEBUG else ["-r"],
|
||||
cwd="resolver",
|
||||
)
|
||||
super().run()
|
||||
|
||||
|
||||
setup(
|
||||
cmdclass={
|
||||
"build_ext": build_ext_with_resolver,
|
||||
},
|
||||
ext_modules=cythonize(
|
||||
[
|
||||
Extension("kloop.loop", ["src/kloop/loop.pyx"]),
|
||||
Extension(
|
||||
"kloop.loop",
|
||||
["src/kloop/loop.pyx"],
|
||||
extra_link_args=[RESOLVER_LIB],
|
||||
depends=[RESOLVER_LIB],
|
||||
),
|
||||
Extension(
|
||||
"kloop.ktls",
|
||||
["src/kloop/ktls.pyx"],
|
||||
|
@ -53,5 +78,5 @@ setup(
|
|||
),
|
||||
],
|
||||
language_level="3",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
|
19
src/kloop/fileio.pxd
Normal file
19
src/kloop/fileio.pxd
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
# kLoop is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
cdef struct FileReader:
|
||||
Loop* loop
|
||||
const char* path
|
||||
int fd, cancelled
|
||||
char* data
|
||||
size_t size, offset
|
||||
RingCallback ring_cb
|
||||
RingCallback done_cb
|
116
src/kloop/fileio.pyx
Normal file
116
src/kloop/fileio.pyx
Normal file
|
@ -0,0 +1,116 @@
|
|||
# Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
# kLoop is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
cdef size_t FILE_READ_BUF_SIZE = 4096
|
||||
|
||||
|
||||
cdef int file_reader_openat_cb(RingCallback* cb) nogil except 0:
|
||||
cdef:
|
||||
int fd = cb.res
|
||||
FileReader* fr = <FileReader*>cb.data
|
||||
|
||||
if fd < 0:
|
||||
fr.done_cb.res = fd
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
if fr.cancelled:
|
||||
fr.done_cb.res = -libc.ECANCELED
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
fr.fd = fd
|
||||
fr.data = <char*>PyMem_RawMalloc(FILE_READ_BUF_SIZE)
|
||||
if fr.data == NULL:
|
||||
fr.done_cb.res = -errno.ENOMEM
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
fr.size = FILE_READ_BUF_SIZE
|
||||
fr.offset = 0
|
||||
fr.ring_cb.callback = file_reader_read_cb
|
||||
if ring_sq_submit_read(
|
||||
&fr.loop.ring.sq,
|
||||
fd,
|
||||
fr.data,
|
||||
FILE_READ_BUF_SIZE,
|
||||
0,
|
||||
&fr.ring_cb,
|
||||
):
|
||||
return 1
|
||||
else:
|
||||
fr.done_cb.res = -errno.EAGAIN
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
|
||||
|
||||
cdef int file_reader_read_cb(RingCallback* cb) nogil except 0:
|
||||
cdef:
|
||||
int read = cb.res
|
||||
FileReader* fr = <FileReader*>cb.data
|
||||
size_t size = fr.size
|
||||
size_t offset = fr.offset
|
||||
|
||||
if read < 0:
|
||||
fr.done_cb.res = read
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
if fr.cancelled:
|
||||
fr.done_cb.res = -libc.ECANCELED
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
offset += read
|
||||
if read > 0 and offset == size:
|
||||
size += FILE_READ_BUF_SIZE
|
||||
if PyMem_RawRealloc(fr.data, size) == NULL:
|
||||
fr.done_cb.res = -errno.ENOMEM
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
fr.size = size
|
||||
fr.offset = offset
|
||||
if ring_sq_submit_read(
|
||||
&fr.loop.ring.sq,
|
||||
fr.fd,
|
||||
fr.data + offset,
|
||||
FILE_READ_BUF_SIZE,
|
||||
offset,
|
||||
&fr.ring_cb,
|
||||
):
|
||||
return 1
|
||||
else:
|
||||
fr.done_cb.res = -errno.EAGAIN
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
else:
|
||||
fr.done_cb.res = 1
|
||||
fr.offset = offset
|
||||
return fr.done_cb.callback(&fr.done_cb)
|
||||
|
||||
|
||||
cdef int file_reader_start(
|
||||
FileReader* fr, Loop* loop, const char* path
|
||||
) nogil:
|
||||
fr.loop = loop
|
||||
fr.done_cb.res = 0
|
||||
fr.fd = 0
|
||||
fr.data = NULL
|
||||
fr.cancelled = 0
|
||||
fr.ring_cb.callback = file_reader_openat_cb
|
||||
fr.ring_cb.data = <void*>fr
|
||||
return ring_sq_submit_openat(
|
||||
&loop.ring.sq,
|
||||
0, # dfd
|
||||
path, # path
|
||||
0, # flags
|
||||
0, # mode
|
||||
&fr.ring_cb
|
||||
)
|
||||
|
||||
|
||||
cdef int file_reader_done(FileReader* fr) nogil:
|
||||
cdef int fd = fr.fd
|
||||
fr.done_cb.res = 0
|
||||
if fr.data != NULL:
|
||||
PyMem_RawFree(fr.data)
|
||||
fr.data = NULL
|
||||
if fd != 0:
|
||||
fr.fd = 0
|
||||
return ring_sq_submit_close(&fr.loop.ring.sq, fd, NULL)
|
||||
return 1
|
|
@ -21,18 +21,22 @@ cdef extern from "signal.h" nogil:
|
|||
int _NSIG
|
||||
|
||||
cdef extern from "sys/socket.h" nogil:
|
||||
enum:
|
||||
SOCK_DGRAM
|
||||
SOCK_STREAM
|
||||
|
||||
ctypedef int socklen_t
|
||||
ctypedef int sa_family_t
|
||||
ctypedef int in_port_t
|
||||
|
||||
int SOL_TLS
|
||||
|
||||
struct in_addr:
|
||||
pass
|
||||
|
||||
struct sockaddr_in:
|
||||
int sin_family
|
||||
int sin_port
|
||||
in_addr sin_addr
|
||||
struct sockaddr:
|
||||
sa_family_t sa_family
|
||||
|
||||
struct msghdr:
|
||||
void* msg_name # Optional address
|
||||
socklen_t msg_namelen # Size of address
|
||||
iovec* msg_iov # Scatter/gather array
|
||||
size_t msg_iovlen # Number of elements in msg_iov
|
||||
void* msg_control # ancillary data, see below
|
||||
|
@ -57,6 +61,7 @@ cdef extern from "sys/socket.h" nogil:
|
|||
const void* option_value,
|
||||
socklen_t option_len,
|
||||
)
|
||||
int bind(int sockfd, const sockaddr* addr, socklen_t addrlen)
|
||||
|
||||
|
||||
cdef extern from "arpa/inet.h" nogil:
|
||||
|
@ -67,3 +72,8 @@ cdef extern from "sys/uio.h" nogil:
|
|||
struct iovec:
|
||||
void* iov_base
|
||||
size_t iov_len
|
||||
|
||||
|
||||
cdef extern from "<errno.h>" nogil:
|
||||
enum:
|
||||
ECANCELED
|
||||
|
|
|
@ -80,6 +80,9 @@ cdef extern from "linux/io_uring.h" nogil:
|
|||
IORING_OP_SENDMSG
|
||||
IORING_OP_RECV
|
||||
IORING_OP_RECVMSG
|
||||
IORING_OP_OPENAT
|
||||
IORING_OP_READ
|
||||
IORING_OP_CLOSE
|
||||
|
||||
struct io_sqring_offsets:
|
||||
__u32 head
|
||||
|
@ -120,6 +123,7 @@ cdef extern from "linux/io_uring.h" nogil:
|
|||
__u32 len # buffer size or number of iovecs
|
||||
__u64 user_data # data to be passed back at completion time
|
||||
__u8 flags # IOSQE_ flags
|
||||
__u32 open_flags
|
||||
|
||||
struct io_uring_cqe:
|
||||
__u64 user_data # data to be passed back at completion time
|
||||
|
|
|
@ -14,6 +14,7 @@ from cpython cimport PyMem_RawMalloc, PyMem_RawFree, PyMem_RawRealloc
|
|||
from cpython cimport PyObject, Py_INCREF, Py_DECREF
|
||||
from libc cimport errno, string
|
||||
from posix cimport mman, unistd, time
|
||||
from posix.types cimport mode_t
|
||||
|
||||
from .includes cimport libc, linux, barrier
|
||||
|
||||
|
@ -22,6 +23,9 @@ include "./queue.pxd"
|
|||
include "./heapq.pxd"
|
||||
include "./uring.pxd"
|
||||
include "./tcp.pxd"
|
||||
include "./udp.pxd"
|
||||
include "./fileio.pxd"
|
||||
include "./resolver.pxd"
|
||||
|
||||
|
||||
cdef struct Loop:
|
||||
|
@ -31,6 +35,7 @@ cdef struct Loop:
|
|||
Queue ready
|
||||
int timer_cancelled_count
|
||||
PyObject* loop
|
||||
CResolver resolver
|
||||
|
||||
|
||||
cdef class KLoopImpl:
|
||||
|
|
|
@ -16,7 +16,6 @@ import functools
|
|||
import inspect
|
||||
import os
|
||||
import reprlib
|
||||
import socket
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
|
@ -39,11 +38,14 @@ cdef int MIN_SCHEDULED_TIMER_HANDLES = 100
|
|||
# that are cancelled before cleanup
|
||||
cdef int MAX_CANCELLED_TIMER_HANDLES_RATIO = 2
|
||||
|
||||
include "./handle.pyx"
|
||||
include "./queue.pyx"
|
||||
include "./heapq.pyx"
|
||||
include "./uring.pyx"
|
||||
include "./tcp.pyx"
|
||||
include "handle.pyx"
|
||||
include "queue.pyx"
|
||||
include "heapq.pyx"
|
||||
include "uring.pyx"
|
||||
include "tcp.pyx"
|
||||
include "udp.pyx"
|
||||
include "fileio.pyx"
|
||||
include "resolver.pyx"
|
||||
|
||||
|
||||
cdef long long monotonic_ns() nogil except -1:
|
||||
|
@ -172,7 +174,7 @@ cdef inline int loop_run_once(
|
|||
Callback* callback
|
||||
long long timeout = -1, now
|
||||
int nready
|
||||
RingCallback* cb
|
||||
RingCallback* cb = NULL
|
||||
|
||||
if scheduled.tail:
|
||||
if not filter_cancelled_calls(loop):
|
||||
|
@ -248,6 +250,7 @@ cdef class KLoopImpl:
|
|||
with nogil:
|
||||
loop_init(&self.loop, depth, ¶ms)
|
||||
|
||||
self.resolver = Resolver.new(self)
|
||||
self.closed = False
|
||||
self.thread_id = None
|
||||
|
||||
|
@ -510,11 +513,25 @@ cdef class KLoopImpl:
|
|||
happy_eyeballs_delay=None,
|
||||
interleave=None,
|
||||
):
|
||||
cdef TCPTransport transport = TCPTransport.new(protocol_factory, self)
|
||||
r = socket.getaddrinfo(host, port)[0]
|
||||
host, port = r[-1]
|
||||
waiter = transport.connect(host, port)
|
||||
return transport, await waiter
|
||||
cdef:
|
||||
TCPTransport transport
|
||||
Resolve resolve
|
||||
object waiter
|
||||
size_t i
|
||||
|
||||
resolve = await self.resolver.lookup_ip(host, port)
|
||||
if not resolve.r.result_len:
|
||||
raise RuntimeError(f"Cannot resolve host: {host!r}")
|
||||
|
||||
transport = TCPTransport.new(protocol_factory, self)
|
||||
exceptions = []
|
||||
for i in range(resolve.r.result_len):
|
||||
try:
|
||||
waiter = transport.connect(resolve.r.result + i)
|
||||
return transport, await waiter
|
||||
except OSError as e:
|
||||
exceptions.append(e)
|
||||
raise exceptions[0]
|
||||
|
||||
|
||||
class KLoop(KLoopImpl, asyncio.AbstractEventLoop):
|
||||
|
|
75
src/kloop/resolver.pxd
Normal file
75
src/kloop/resolver.pxd
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
# kLoop is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
cdef extern from * nogil:
|
||||
int resolver_init(
|
||||
CResolver* resolver,
|
||||
char* resolv_conf_data,
|
||||
size_t resolv_conf_data_size,
|
||||
char* hosts_conf_data,
|
||||
size_t hosts_conf_data_size,
|
||||
)
|
||||
int resolver_lookup_ip(
|
||||
void* resolver,
|
||||
void* resolve,
|
||||
char* host,
|
||||
size_t length,
|
||||
libc.in_port_t port,
|
||||
)
|
||||
void resolver_run_until_stalled(void* rust_resolver)
|
||||
void waker_wake(void* waker)
|
||||
void waker_forget(void* waker)
|
||||
|
||||
|
||||
cdef struct CResolver:
|
||||
Loop* loop
|
||||
Callback* cb
|
||||
FileReader resolv_conf
|
||||
FileReader hosts_conf
|
||||
int res
|
||||
void* rust_resolver
|
||||
|
||||
|
||||
cdef class Resolver:
|
||||
cdef:
|
||||
CResolver resolver
|
||||
KLoopImpl loop
|
||||
Handle handle
|
||||
object waiter
|
||||
bint initialized
|
||||
|
||||
@staticmethod
|
||||
cdef Resolver new(KLoopImpl loop)
|
||||
cdef init_cb(self)
|
||||
cdef err_cb(self, exc)
|
||||
|
||||
|
||||
cdef struct CResolve:
|
||||
CResolver* resolver
|
||||
libc.sockaddr* result
|
||||
size_t result_len, result_size
|
||||
Callback* cb
|
||||
int res
|
||||
char* host
|
||||
size_t host_len
|
||||
libc.in_port_t port
|
||||
|
||||
|
||||
cdef class Resolve:
|
||||
cdef:
|
||||
CResolve r
|
||||
Handle handle
|
||||
object waiter
|
||||
object host
|
||||
|
||||
@staticmethod
|
||||
cdef new(Resolver resolver, host, port)
|
||||
cdef resolve_cb(self)
|
175
src/kloop/resolver.pyx
Normal file
175
src/kloop/resolver.pyx
Normal file
|
@ -0,0 +1,175 @@
|
|||
# Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
# kLoop is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
cdef const char* RESOLV_CONF = "/etc/resolv.conf"
|
||||
cdef const char* HOSTS_CONF = "/etc/hosts"
|
||||
cdef size_t SOCKADDR_CHUNK_SIZE = 4
|
||||
|
||||
|
||||
cdef int resolve_cb(RingCallback* cb) nogil except 0:
|
||||
cdef:
|
||||
CResolver* r = <CResolver*>cb.data
|
||||
int rv = 1
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
cdef int resolver_read_file_cb(RingCallback* cb) nogil except 0:
|
||||
cdef:
|
||||
CResolver* r = <CResolver*>cb.data
|
||||
int rv = 1
|
||||
void* ptr
|
||||
|
||||
if r.hosts_conf.done_cb.res == 0 or r.resolv_conf.done_cb.res == 0:
|
||||
if cb.res < 0:
|
||||
r.resolv_conf.cancelled = r.hosts_conf.cancelled = 1
|
||||
else:
|
||||
r.res = min(r.hosts_conf.done_cb.res, r.resolv_conf.done_cb.res)
|
||||
if r.res > 0:
|
||||
r.res = resolver_init(
|
||||
r,
|
||||
r.resolv_conf.data,
|
||||
r.resolv_conf.offset,
|
||||
r.hosts_conf.data,
|
||||
r.hosts_conf.offset,
|
||||
)
|
||||
rv = queue_push(&r.loop.ready, r.cb)
|
||||
if not file_reader_done(&r.resolv_conf):
|
||||
# TODO: fd not closed?
|
||||
pass
|
||||
if not file_reader_done(&r.hosts_conf):
|
||||
# TODO: fd not closed?
|
||||
pass
|
||||
return rv
|
||||
|
||||
|
||||
cdef extern libc.sockaddr* resolve_prep_addr(CResolve* r) nogil:
|
||||
cdef size_t l = r.result_len, size = r.result_size
|
||||
if l == size:
|
||||
size += SOCKADDR_CHUNK_SIZE
|
||||
if PyMem_RawRealloc(r.result, sizeof(libc.sockaddr) * size) == NULL:
|
||||
return NULL
|
||||
r.result_size = size
|
||||
r.result_len = l + 1
|
||||
return r.result + l
|
||||
|
||||
|
||||
cdef extern int resolve_done_cb(CResolve* r) nogil:
|
||||
return queue_push(&r.resolver.loop.ready, r.cb)
|
||||
|
||||
|
||||
cdef extern void resolver_set(CResolver* resolver, void* rust_resolver) nogil:
|
||||
resolver.rust_resolver = rust_resolver
|
||||
|
||||
|
||||
cdef class Resolver:
|
||||
@staticmethod
|
||||
cdef Resolver new(KLoopImpl loop):
|
||||
cdef:
|
||||
Resolver rv = Resolver.__new__(Resolver)
|
||||
CResolver* r = &rv.resolver
|
||||
rv.loop = loop
|
||||
r.loop = &loop.loop
|
||||
r.resolv_conf.done_cb.callback = resolver_read_file_cb
|
||||
r.resolv_conf.done_cb.data = r
|
||||
r.hosts_conf.done_cb.callback = resolver_read_file_cb
|
||||
r.hosts_conf.done_cb.data = r
|
||||
return rv
|
||||
|
||||
async def ensure_initialized(self):
|
||||
cdef CResolver* r
|
||||
|
||||
if self.initialized:
|
||||
return
|
||||
waiter = self.waiter
|
||||
if waiter is None:
|
||||
r = &self.resolver
|
||||
waiter = self.waiter = self.loop.create_future()
|
||||
if not file_reader_start(&r.resolv_conf, r.loop, RESOLV_CONF):
|
||||
self.err_cb(ValueError("Submission queue is full!"))
|
||||
elif not file_reader_start(&r.hosts_conf, r.loop, HOSTS_CONF):
|
||||
r.resolv_conf.cancelled = 1
|
||||
self.err_cb(ValueError("Submission queue is full!"))
|
||||
else:
|
||||
self.handle = Handle(self.init_cb, (self,), self.loop, None)
|
||||
r.cb = &self.handle.cb
|
||||
await waiter
|
||||
|
||||
async def reload_config(self, *, force=False):
|
||||
if self.initialized:
|
||||
waiter = self.waiter
|
||||
if waiter is None:
|
||||
waiter = self.waiter = self.loop.create_future()
|
||||
self.err_cb(NotImplementedError())
|
||||
await waiter
|
||||
else:
|
||||
await self.ensure_initialized()
|
||||
|
||||
cdef init_cb(self):
|
||||
cdef int res = self.resolver.res
|
||||
|
||||
if res < 0:
|
||||
try:
|
||||
errno.errno = -res
|
||||
PyErr_SetFromErrno(IOError)
|
||||
except IOError as e:
|
||||
self.waiter.set_exception(e)
|
||||
else:
|
||||
self.waiter.set_result(None)
|
||||
|
||||
cdef err_cb(self, exc):
|
||||
waiter, self.waiter = self.waiter, None
|
||||
if waiter is not None:
|
||||
waiter.set_exception(exc)
|
||||
|
||||
async def lookup_ip(self, host, port):
|
||||
await self.ensure_initialized()
|
||||
return await Resolve.new(self, host, port)
|
||||
|
||||
|
||||
cdef class Resolve:
|
||||
@staticmethod
|
||||
cdef new(Resolver resolver, host, port):
|
||||
cdef:
|
||||
Resolve rv = Resolve.__new__(Resolve)
|
||||
CResolve* r = &rv.r
|
||||
rv.host = host.encode("utf-8")
|
||||
rv.waiter = resolver.loop.create_future()
|
||||
r.resolver = &resolver.resolver
|
||||
r.host = <char*>rv.host
|
||||
r.host_len = len(rv.host)
|
||||
r.port = port
|
||||
r.result = <libc.sockaddr*>PyMem_RawMalloc(
|
||||
sizeof(libc.sockaddr) * SOCKADDR_CHUNK_SIZE
|
||||
)
|
||||
if r.result == NULL:
|
||||
raise MemoryError
|
||||
r.result_size = SOCKADDR_CHUNK_SIZE
|
||||
rv.handle = Handle(rv.resolve_cb, (rv,), resolver.loop, None)
|
||||
r.cb = &rv.handle.cb
|
||||
return rv
|
||||
|
||||
def __await__(self):
|
||||
cdef CResolve* r = &self.r
|
||||
resolver_lookup_ip(r.resolver.rust_resolver, r, r.host, r.host_len, r.port)
|
||||
return self.waiter.__await__()
|
||||
|
||||
def __dealloc__(self):
|
||||
cdef CResolve* r = &self.r
|
||||
r.host = NULL
|
||||
r.host_len = 0
|
||||
if r.result != NULL:
|
||||
PyMem_RawFree(r.result)
|
||||
r.result = NULL
|
||||
r.result_size = 0
|
||||
|
||||
cdef resolve_cb(self):
|
||||
self.waiter.set_result(self)
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
cdef struct TCPConnect:
|
||||
int fd
|
||||
libc.sockaddr_in addr
|
||||
libc.sockaddr* addr
|
||||
RingCallback ring_cb
|
||||
Loop* loop
|
||||
Callback* cb
|
||||
|
@ -24,11 +24,10 @@ cdef class TCPTransport:
|
|||
TCPConnect connector
|
||||
object waiter
|
||||
object protocol_factory
|
||||
object host_bytes
|
||||
Handle handle
|
||||
|
||||
@staticmethod
|
||||
cdef TCPTransport new(object protocol_factory, KLoopImpl loop)
|
||||
|
||||
cdef connect(self, host, port)
|
||||
cdef connect(self, libc.sockaddr* addr)
|
||||
cdef connect_cb(self)
|
||||
|
|
|
@ -13,7 +13,7 @@ cdef int tcp_connect(TCPConnect* connector) nogil:
|
|||
return ring_sq_submit_connect(
|
||||
&connector.loop.ring.sq,
|
||||
connector.fd,
|
||||
&connector.addr,
|
||||
connector.addr,
|
||||
&connector.ring_cb,
|
||||
)
|
||||
|
||||
|
@ -29,29 +29,22 @@ cdef class TCPTransport:
|
|||
cdef TCPTransport rv = TCPTransport.__new__(TCPTransport)
|
||||
rv.protocol_factory = protocol_factory
|
||||
rv.loop = loop
|
||||
rv.connector.loop = &loop.loop
|
||||
rv.connector.ring_cb.callback = tcp_connect_cb
|
||||
rv.connector.ring_cb.data = &rv.connector
|
||||
return rv
|
||||
|
||||
cdef connect(self, host, port):
|
||||
cdef connect(self, libc.sockaddr* addr):
|
||||
cdef:
|
||||
int fd
|
||||
TCPConnect* c = &self.connector
|
||||
|
||||
fd = libc.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||
fd = libc.socket(addr.sa_family, libc.SOCK_STREAM, 0)
|
||||
if fd == -1:
|
||||
PyErr_SetFromErrno(IOError)
|
||||
return
|
||||
self.host_bytes = host.encode()
|
||||
if not libc.inet_pton(
|
||||
socket.AF_INET, <char*>self.host_bytes, &c.addr.sin_addr
|
||||
):
|
||||
PyErr_SetFromErrno(IOError)
|
||||
return
|
||||
c.addr.sin_family = socket.AF_INET
|
||||
c.addr.sin_port = libc.htons(port)
|
||||
c.addr = addr
|
||||
c.fd = self.fd = fd
|
||||
c.loop = &self.loop.loop
|
||||
c.ring_cb.callback = tcp_connect_cb
|
||||
c.ring_cb.data = c
|
||||
self.handle = Handle(self.connect_cb, (self,), self.loop, None)
|
||||
c.cb = &self.handle.cb
|
||||
if not tcp_connect(c):
|
||||
|
@ -61,6 +54,11 @@ cdef class TCPTransport:
|
|||
|
||||
cdef connect_cb(self):
|
||||
if self.connector.ring_cb.res != 0:
|
||||
if not ring_sq_submit_close(
|
||||
&self.loop.loop.ring.sq, self.fd, NULL
|
||||
):
|
||||
# TODO: fd not closed?
|
||||
pass
|
||||
try:
|
||||
errno.errno = abs(self.connector.ring_cb.res)
|
||||
PyErr_SetFromErrno(IOError)
|
||||
|
|
18
src/kloop/udp.pxd
Normal file
18
src/kloop/udp.pxd
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
# kLoop is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
cdef struct UDPSend:
|
||||
int fd
|
||||
libc.iovec vec
|
||||
libc.msghdr msg
|
||||
RingCallback callback
|
||||
CResolver* resolver
|
||||
void* rust_waker
|
69
src/kloop/udp.pyx
Normal file
69
src/kloop/udp.pyx
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Copyright (c) 2022 Fantix King http://fantix.pro
|
||||
# kLoop is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
cdef extern int udp_bind(libc.sockaddr* addr, libc.socklen_t addrlen) nogil:
|
||||
cdef int fd = libc.socket(addr.sa_family, libc.SOCK_DGRAM, 0)
|
||||
if fd == -1:
|
||||
return -1
|
||||
if libc.bind(fd, addr, addrlen) == -1:
|
||||
# TODO: close fd
|
||||
return -1
|
||||
return fd
|
||||
|
||||
|
||||
cdef extern unsigned long udp_send_init(int fd, CResolver* resolver) nogil:
|
||||
cdef UDPSend* rv
|
||||
rv = <UDPSend*>PyMem_RawMalloc(sizeof(UDPSend))
|
||||
if rv == NULL:
|
||||
return 0
|
||||
string.memset(rv, 0, sizeof(UDPSend))
|
||||
rv.fd = fd
|
||||
rv.resolver = resolver
|
||||
rv.msg.msg_iov = &rv.vec
|
||||
rv.msg.msg_iovlen = 1
|
||||
rv.callback.data = <void*>rv
|
||||
rv.callback.callback = udp_send_cb
|
||||
return <unsigned long>rv
|
||||
|
||||
|
||||
cdef int udp_send_cb(RingCallback* cb) nogil except 0:
|
||||
cdef UDPSend* send = <UDPSend*>cb.data
|
||||
waker_wake(send.rust_waker)
|
||||
resolver_run_until_stalled(send.resolver.rust_resolver)
|
||||
return 1
|
||||
|
||||
|
||||
cdef extern int udp_send_poll(
|
||||
unsigned long send_in,
|
||||
char* data,
|
||||
size_t datalen,
|
||||
libc.sockaddr* addr,
|
||||
libc.socklen_t addrlen,
|
||||
void* waker,
|
||||
) nogil:
|
||||
cdef UDPSend* send = <UDPSend*>send_in
|
||||
if send.vec.iov_base == NULL:
|
||||
send.vec.iov_base = data
|
||||
send.vec.iov_len = datalen
|
||||
send.msg.msg_name = <void*>addr
|
||||
send.msg.msg_namelen = addrlen
|
||||
send.rust_waker = waker
|
||||
return ring_sq_submit_sendmsg(
|
||||
&send.resolver.loop.ring.sq,
|
||||
send.fd,
|
||||
&send.msg,
|
||||
&send.callback,
|
||||
) - 1
|
||||
else:
|
||||
waker_forget(waker)
|
||||
if send.vec.iov_base != data or send.vec.iov_len != datalen:
|
||||
return -1
|
||||
return send.callback.res or -1
|
|
@ -176,12 +176,13 @@ cdef inline void ring_cq_pop(CompletionQueue* cq, RingCallback** callback) nogil
|
|||
head = cq.khead[0]
|
||||
cqe = cq.cqes + (head & cq.kring_mask[0])
|
||||
ret = <RingCallback*>cqe.user_data
|
||||
ret.res = cqe.res
|
||||
callback[0] = ret
|
||||
if ret != NULL:
|
||||
ret.res = cqe.res
|
||||
callback[0] = ret
|
||||
barrier.io_uring_smp_store_release(cq.khead, head + 1)
|
||||
|
||||
|
||||
cdef inline int ring_sq_submit(
|
||||
cdef inline linux.io_uring_sqe* ring_sq_submit(
|
||||
SubmissionQueue* sq,
|
||||
linux.__u8 op,
|
||||
int fd,
|
||||
|
@ -209,15 +210,15 @@ cdef inline int ring_sq_submit(
|
|||
if link:
|
||||
sqe.flags = linux.IOSQE_IO_LINK
|
||||
sqe.user_data = <linux.__u64>callback
|
||||
return 1
|
||||
return sqe
|
||||
else:
|
||||
return 0
|
||||
return NULL
|
||||
|
||||
|
||||
cdef int ring_sq_submit_connect(
|
||||
SubmissionQueue* sq, int fd, libc.sockaddr_in* addr, RingCallback* callback
|
||||
SubmissionQueue* sq, int fd, libc.sockaddr* addr, RingCallback* callback
|
||||
) nogil:
|
||||
return ring_sq_submit(
|
||||
return 1 if ring_sq_submit(
|
||||
sq,
|
||||
linux.IORING_OP_CONNECT,
|
||||
fd,
|
||||
|
@ -226,4 +227,83 @@ cdef int ring_sq_submit_connect(
|
|||
sizeof(addr[0]),
|
||||
0,
|
||||
callback,
|
||||
) else 0
|
||||
|
||||
|
||||
cdef int ring_sq_submit_openat(
|
||||
SubmissionQueue* sq,
|
||||
int dfd,
|
||||
const char* path,
|
||||
int flags,
|
||||
mode_t mode,
|
||||
RingCallback* callback,
|
||||
) nogil:
|
||||
cdef linux.io_uring_sqe* sqe = ring_sq_submit(
|
||||
sq,
|
||||
linux.IORING_OP_OPENAT,
|
||||
dfd,
|
||||
<unsigned long>path,
|
||||
mode,
|
||||
0,
|
||||
0,
|
||||
callback,
|
||||
)
|
||||
if sqe == NULL:
|
||||
return 0
|
||||
else:
|
||||
sqe.open_flags = flags
|
||||
return 1
|
||||
|
||||
|
||||
cdef int ring_sq_submit_read(
|
||||
SubmissionQueue* sq,
|
||||
int fd,
|
||||
char* buf,
|
||||
unsigned nbytes,
|
||||
linux.__u64 offset,
|
||||
RingCallback* callback,
|
||||
) nogil:
|
||||
return 1 if ring_sq_submit(
|
||||
sq,
|
||||
linux.IORING_OP_READ,
|
||||
fd,
|
||||
<unsigned long>buf,
|
||||
nbytes,
|
||||
offset,
|
||||
0,
|
||||
callback,
|
||||
) else 0
|
||||
|
||||
|
||||
cdef int ring_sq_submit_close(
|
||||
SubmissionQueue* sq,
|
||||
int fd,
|
||||
RingCallback * callback,
|
||||
) nogil:
|
||||
return 1 if ring_sq_submit(
|
||||
sq,
|
||||
linux.IORING_OP_CLOSE,
|
||||
fd,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
callback,
|
||||
) else 0
|
||||
|
||||
cdef int ring_sq_submit_sendmsg(
|
||||
SubmissionQueue* sq,
|
||||
int fd,
|
||||
const libc.msghdr *msg,
|
||||
RingCallback* callback,
|
||||
) nogil:
|
||||
return 1 if ring_sq_submit(
|
||||
sq,
|
||||
linux.IORING_OP_SENDMSG,
|
||||
fd,
|
||||
<unsigned long>msg,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
callback,
|
||||
) else 0
|
||||
|
|
Loading…
Reference in a new issue