You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-29 22:01:14 +03:00
WIP: better listeners
- listen on UNIX domain sockets - handle TLS stuff - allow mounting only some resources
This commit is contained in:
317
Cargo.lock
generated
317
Cargo.lock
generated
@ -96,15 +96,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.65"
|
||||
@ -130,9 +121,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.3.14"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695"
|
||||
checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"flate2",
|
||||
@ -230,7 +221,7 @@ dependencies = [
|
||||
"http",
|
||||
"hyper",
|
||||
"ring",
|
||||
"time 0.3.14",
|
||||
"time 0.3.15",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tracing",
|
||||
@ -362,7 +353,7 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"regex",
|
||||
"ring",
|
||||
"time 0.3.14",
|
||||
"time 0.3.15",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@ -462,10 +453,10 @@ version = "0.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e93b0c93a3b963da946a0b8ef3853a7252298eb75cdbfb21dad60f5ed0ded861"
|
||||
dependencies = [
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"num-integer",
|
||||
"ryu",
|
||||
"time 0.3.14",
|
||||
"time 0.3.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -507,7 +498,7 @@ dependencies = [
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"matchit 0.5.0",
|
||||
"memchr",
|
||||
"mime",
|
||||
@ -537,7 +528,7 @@ dependencies = [
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"matchit 0.6.0",
|
||||
"memchr",
|
||||
"mime",
|
||||
@ -860,9 +851,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.2"
|
||||
version = "4.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c9484ccdc4cb8e7b117cbd0eb150c7c0f04464854e4679aeb50ef03b32d003"
|
||||
checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@ -875,9 +866,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.1"
|
||||
version = "4.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca689d7434ce44517a12a89456b2be4d1ea1cafcd8f581978c03d45f5a5c12a7"
|
||||
checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@ -895,6 +886,16 @@ dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.0"
|
||||
@ -923,7 +924,7 @@ dependencies = [
|
||||
"rand",
|
||||
"sha2 0.10.6",
|
||||
"subtle",
|
||||
"time 0.3.14",
|
||||
"time 0.3.15",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
@ -1104,15 +1105,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.10"
|
||||
version = "0.9.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
|
||||
checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"once_cell",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
@ -1128,19 +1128,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
|
||||
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f2b443d17d49dad5ef0ede301c3179cc923b8822f3393b4d2c28c269dd4a122"
|
||||
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
@ -1192,13 +1191,57 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.1"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d14f329cfbaf5d0e06b5e87fff7e265d2673c5ea7d2c27691a2c107db1442a0"
|
||||
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.1"
|
||||
@ -1488,9 +1531,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "figment"
|
||||
version = "0.10.7"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e3bd154d9ae2f1bb0ada5b7eebd56529513efa5de7d2fc8c6adf33bc43260cf"
|
||||
checksum = "4e56602b469b2201400dec66a66aec5a9b8761ee97cd1b8c96ab2483fcc16cc9"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"parking_lot 0.12.1",
|
||||
@ -1727,9 +1770,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.12.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7391856def869c1c81063a03457c676fbcd419709c3dfb33d8d319de484b154d"
|
||||
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core",
|
||||
@ -1869,7 +1912,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
|
||||
dependencies = [
|
||||
"bytes 1.2.1",
|
||||
"fnv",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1928,7 +1971,7 @@ dependencies = [
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio",
|
||||
@ -1981,17 +2024,28 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.50"
|
||||
version = "0.1.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0"
|
||||
checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@ -2132,9 +2186,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
|
||||
[[package]]
|
||||
name = "ittapi"
|
||||
@ -2253,9 +2307,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.133"
|
||||
version = "0.2.135"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
|
||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
@ -2263,6 +2317,15 @@ version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.0.46"
|
||||
@ -2366,6 +2429,7 @@ dependencies = [
|
||||
"mas-email",
|
||||
"mas-handlers",
|
||||
"mas-http",
|
||||
"mas-listener",
|
||||
"mas-policy",
|
||||
"mas-router",
|
||||
"mas-static-files",
|
||||
@ -2380,6 +2444,7 @@ dependencies = [
|
||||
"opentelemetry-semantic-conventions",
|
||||
"opentelemetry-zipkin",
|
||||
"prometheus",
|
||||
"rustls 0.20.6",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"tokio",
|
||||
@ -2409,6 +2474,7 @@ dependencies = [
|
||||
"mas-keystore",
|
||||
"pem-rfc7468",
|
||||
"rand",
|
||||
"rustls-pemfile",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2607,6 +2673,18 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mas-listener"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"hyper",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mas-policy"
|
||||
version = "0.1.0"
|
||||
@ -2828,6 +2906,16 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.1"
|
||||
@ -3142,6 +3230,12 @@ version = "6.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "p256"
|
||||
version = "0.11.1"
|
||||
@ -3319,9 +3413,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048"
|
||||
checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
@ -3329,9 +3423,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1"
|
||||
checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@ -3339,9 +3433,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c"
|
||||
checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
@ -3352,9 +3446,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6"
|
||||
checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
@ -3444,12 +3538,13 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs1"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e3a81571d9455414f4d59ce2830bc9d2654e2efc5460fd67b0e0a6a36b6753a"
|
||||
checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719"
|
||||
dependencies = [
|
||||
"der",
|
||||
"pkcs8",
|
||||
"spki",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@ -3512,9 +3607,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.1.19"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a49e86d2c26a24059894a3afa13fd17d063419b05dfb83f06d9c3566060c3f5a"
|
||||
checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
@ -3546,9 +3641,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.44"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -3852,9 +3947,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.7.0-rc.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237a0c597c9fdb501f592f52e8ab754dc43787dd8a8bf20c191f562817d50b08"
|
||||
checksum = "96144aaefe4fa4c1846c404d1ccc3dc45c9b15c2e41591597294cb7ccc2dbfd7"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"digest 0.10.5",
|
||||
@ -3922,9 +4017,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.35.10"
|
||||
version = "0.35.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af895b90e5c071badc3136fc10ff0bcfc98747eadbaf43ed8f214e07ba8f8477"
|
||||
checksum = "fbb2fda4666def1433b1b05431ab402e42a1084285477222b72d6c564c417cef"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@ -4028,9 +4123,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed"
|
||||
checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dyn-clone",
|
||||
@ -4042,9 +4137,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743"
|
||||
checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4058,6 +4153,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
|
||||
|
||||
[[package]]
|
||||
name = "scrypt"
|
||||
version = "0.10.0"
|
||||
@ -4179,11 +4280,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.85"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"
|
||||
dependencies = [
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
@ -4195,7 +4296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
@ -4213,7 +4314,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time 0.3.14",
|
||||
"time 0.3.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4235,7 +4336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
@ -4295,9 +4396,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "1.6.3"
|
||||
version = "1.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deb766570a2825fa972bceff0d195727876a9cdf2460ab2e52d455dc2de47fd9"
|
||||
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||
dependencies = [
|
||||
"digest 0.10.5",
|
||||
"rand_core",
|
||||
@ -4335,9 +4436,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
@ -4420,7 +4521,7 @@ dependencies = [
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"indexmap",
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"libc",
|
||||
"log",
|
||||
"md-5",
|
||||
@ -4532,9 +4633,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.101"
|
||||
version = "1.0.102"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
|
||||
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4662,11 +4763,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.14"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b"
|
||||
checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c"
|
||||
dependencies = [
|
||||
"itoa 1.0.3",
|
||||
"itoa 1.0.4",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"serde",
|
||||
@ -4759,9 +4860,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af"
|
||||
checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
@ -4809,9 +4910,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tonic"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11cd56bdb54ef93935a6a79dbd1d91f1ebd4c64150fd61654031fd6b8b775c91"
|
||||
checksum = "55b9af819e54b8f33d453655bef9b9acc171568fb49523078d0cc4e7484200ec"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
@ -4841,9 +4942,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tonic-build"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fbcd2800e34e743b9ae795867d5f77b535d3a3be69fd731e39145719752df8c"
|
||||
checksum = "48c6fd7c2581e36d63388a9e04c350c21beb7a8b059580b2e93993c526899ddc"
|
||||
dependencies = [
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
@ -4902,9 +5003,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
|
||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
@ -4914,9 +5015,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.36"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
@ -4932,15 +5033,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"time 0.3.14",
|
||||
"time 0.3.15",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.22"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4949,9 +5050,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.29"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
|
||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
@ -4994,12 +5095,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.15"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
|
||||
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
@ -5124,9 +5225,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
@ -5197,9 +5298,9 @@ checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.1.2"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
|
||||
checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
@ -5314,9 +5415,9 @@ checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-encoder"
|
||||
version = "0.17.0"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e7ca71c70a6de5b10968ae4d298e548366d9cd9588176e6ff8866f3c49c96ee"
|
||||
checksum = "c64ac98d5d61192cc45c701b7e4bd0b9aff91e2edfc7a088406cfe2288581e2c"
|
||||
dependencies = [
|
||||
"leb128",
|
||||
]
|
||||
@ -5520,9 +5621,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wast"
|
||||
version = "47.0.0"
|
||||
version = "47.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117ccfc4262e62a28a13f0548a147f19ffe71e8a08be802af23ae4ea0bedad73"
|
||||
checksum = "02b98502f3978adea49551e801a6687678e6015317d7d9470a67fe813393f2a8"
|
||||
dependencies = [
|
||||
"leb128",
|
||||
"memchr",
|
||||
|
@ -20,6 +20,7 @@ argon2 = { version = "0.4.1", features = ["password-hash"] }
|
||||
watchman_client = "0.8.0"
|
||||
atty = "0.2.14"
|
||||
listenfd = "1.0.0"
|
||||
rustls = "0.20.6"
|
||||
|
||||
tracing = "0.1.36"
|
||||
tracing-appender = "0.2.2"
|
||||
@ -44,6 +45,7 @@ mas-static-files = { path = "../static-files" }
|
||||
mas-storage = { path = "../storage" }
|
||||
mas-tasks = { path = "../tasks" }
|
||||
mas-templates = { path = "../templates" }
|
||||
mas-listener = { path = "../listener" }
|
||||
|
||||
[dev-dependencies]
|
||||
indoc = "1.0.7"
|
||||
|
@ -12,12 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::{net::SocketAddr, sync::Arc, time::Duration};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use futures_util::{
|
||||
future::FutureExt,
|
||||
future::{FutureExt, OptionFuture},
|
||||
stream::{StreamExt, TryStreamExt},
|
||||
};
|
||||
use hyper::Server;
|
||||
@ -25,6 +25,7 @@ use mas_config::RootConfig;
|
||||
use mas_email::Mailer;
|
||||
use mas_handlers::{AppState, MatrixHomeserver};
|
||||
use mas_http::ServerLayer;
|
||||
use mas_listener::{maybe_tls::MaybeTlsAcceptor, unix_or_tcp::UnixOrTcpListener};
|
||||
use mas_policy::PolicyFactory;
|
||||
use mas_router::{Route, UrlBuilder};
|
||||
use mas_storage::MIGRATOR;
|
||||
@ -245,39 +246,103 @@ impl Options {
|
||||
});
|
||||
|
||||
let signal = shutdown_signal().shared();
|
||||
let shutdown_signal = signal.clone();
|
||||
let mut fd_manager = listenfd::ListenFd::from_env();
|
||||
|
||||
let futs = listeners_config
|
||||
.into_iter()
|
||||
.map(|listener_config| {
|
||||
let listeners = listeners_config.into_iter().map(|listener_config| {
|
||||
// We have to borrow it here, not in the nested closure
|
||||
let fd_manager = &mut fd_manager;
|
||||
|
||||
// Let's first grab all the listeners in a synchronous manner
|
||||
// This helps with the fd_manager mutable borrow
|
||||
let listeners: Result<Vec<UnixOrTcpListener>, _> = listener_config
|
||||
.binds
|
||||
.iter()
|
||||
.map(move |bind_config| bind_config.listener(fd_manager))
|
||||
.collect();
|
||||
|
||||
Ok((listener_config, listeners?))
|
||||
});
|
||||
|
||||
// Now that we have the listeners ready, we can do the rest concurrently
|
||||
futures_util::stream::iter(listeners)
|
||||
.try_for_each_concurrent(None, move |(config, listeners)| {
|
||||
let signal = signal.clone();
|
||||
let router = mas_handlers::router(state.clone())
|
||||
.nest(mas_router::StaticAsset::route(), static_files.clone())
|
||||
.layer(ServerLayer::default());
|
||||
|
||||
let mut futs: Vec<_> = Vec::with_capacity(listener_config.binds.len());
|
||||
for bind in listener_config.binds {
|
||||
let listener = bind.listener(&mut fd_manager)?;
|
||||
let router = router.clone();
|
||||
let mut router = mas_handlers::empty_router(state.clone());
|
||||
|
||||
let addr = listener.local_addr()?;
|
||||
info!("Listening on http://{addr}");
|
||||
|
||||
let fut = Server::from_tcp(listener)?
|
||||
.serve(router.into_make_service_with_connect_info::<SocketAddr>())
|
||||
.with_graceful_shutdown(signal.clone());
|
||||
futs.push(fut);
|
||||
for resource in config.resources {
|
||||
router = match resource {
|
||||
mas_config::HttpResource::Health => {
|
||||
router.merge(mas_handlers::healthcheck_router(state.clone()))
|
||||
}
|
||||
mas_config::HttpResource::Discovery => {
|
||||
router.merge(mas_handlers::discovery_router(state.clone()))
|
||||
}
|
||||
mas_config::HttpResource::Human => {
|
||||
router.merge(mas_handlers::human_router(state.clone()))
|
||||
}
|
||||
mas_config::HttpResource::Static => {
|
||||
router.nest(mas_router::StaticAsset::route(), static_files.clone())
|
||||
}
|
||||
mas_config::HttpResource::OAuth => {
|
||||
router.merge(mas_handlers::api_router(state.clone()))
|
||||
}
|
||||
mas_config::HttpResource::Compat => {
|
||||
router.merge(mas_handlers::compat_router(state.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::Ok(futures_util::future::try_join_all(futs))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let router = router.layer(ServerLayer::default());
|
||||
|
||||
futures_util::future::try_join_all(futs).await?;
|
||||
async move {
|
||||
let tls_config: OptionFuture<_> = config
|
||||
.tls
|
||||
.map(|tls_config| async move {
|
||||
let (key, chain) = tls_config.load().await?;
|
||||
let key = rustls::PrivateKey(key);
|
||||
let chain = chain.into_iter().map(rustls::Certificate).collect();
|
||||
let mut config = rustls::ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(chain, key)
|
||||
.context("failed to build TLS server config")?;
|
||||
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
||||
anyhow::Ok(Arc::new(config))
|
||||
})
|
||||
.into();
|
||||
let tls_config = tls_config.await.transpose()?;
|
||||
|
||||
futures_util::stream::iter(listeners)
|
||||
.map(Ok)
|
||||
.try_for_each_concurrent(None, move |listener| {
|
||||
let listener = MaybeTlsAcceptor::new(tls_config.clone(), listener);
|
||||
|
||||
// Unless there is something really bad happening, we should be able to
|
||||
// grab the local_addr here. Panicking here if it is not the case is
|
||||
// probably fine.
|
||||
let addr = listener.local_addr().unwrap();
|
||||
if listener.is_secure() {
|
||||
info!("Listening on https://{addr:?}");
|
||||
} else {
|
||||
info!("Listening on http://{addr:?}");
|
||||
}
|
||||
|
||||
Server::builder(listener)
|
||||
.serve(router.clone().into_make_service())
|
||||
.with_graceful_shutdown(signal.clone())
|
||||
})
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(())
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
// This ensures we're running, even if no listener are setup
|
||||
// This is useful for only running the task runner
|
||||
signal.await;
|
||||
shutdown_signal.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ lettre = { version = "0.10.1", default-features = false, features = ["serde", "b
|
||||
listenfd = "1.0.0"
|
||||
|
||||
pem-rfc7468 = "0.6.0"
|
||||
rustls-pemfile = "1.0.1"
|
||||
rand = "0.8.5"
|
||||
|
||||
indoc = "1.0.7"
|
||||
|
@ -13,22 +13,23 @@
|
||||
// limitations under the License.
|
||||
|
||||
use std::{
|
||||
net::{SocketAddr, TcpListener},
|
||||
borrow::Cow,
|
||||
io::Cursor,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, ToSocketAddrs},
|
||||
ops::Deref,
|
||||
os::unix::net::UnixListener,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{bail, Context};
|
||||
use async_trait::async_trait;
|
||||
use listenfd::ListenFd;
|
||||
use mas_keystore::PrivateKey;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use super::ConfigurationSection;
|
||||
|
||||
fn default_http_address() -> String {
|
||||
"[::]:8080".into()
|
||||
}
|
||||
use super::{secrets::PasswordOrFile, ConfigurationSection};
|
||||
|
||||
fn default_public_base() -> Url {
|
||||
"http://[::]:8080".parse().unwrap()
|
||||
@ -47,9 +48,31 @@ fn http_address_example_4() -> &'static str {
|
||||
"0.0.0.0:8080"
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum UnixOrTcp {
|
||||
Unix,
|
||||
Tcp,
|
||||
}
|
||||
|
||||
impl UnixOrTcp {
|
||||
pub const fn unix() -> Self {
|
||||
Self::Unix
|
||||
}
|
||||
|
||||
pub const fn tcp() -> Self {
|
||||
Self::Tcp
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
|
||||
#[serde(untagged)]
|
||||
pub enum BindConfig {
|
||||
Listen {
|
||||
host: Option<String>,
|
||||
port: u16,
|
||||
},
|
||||
|
||||
Address {
|
||||
#[schemars(
|
||||
example = "http_address_example_1",
|
||||
@ -59,39 +82,202 @@ pub enum BindConfig {
|
||||
)]
|
||||
address: String,
|
||||
},
|
||||
|
||||
Unix {
|
||||
socket: PathBuf,
|
||||
},
|
||||
|
||||
FileDescriptor {
|
||||
fd: usize,
|
||||
|
||||
#[serde(default = "UnixOrTcp::tcp")]
|
||||
kind: UnixOrTcp,
|
||||
},
|
||||
}
|
||||
|
||||
impl BindConfig {
|
||||
pub fn listener(self, fd_manager: &mut ListenFd) -> Result<TcpListener, anyhow::Error> {
|
||||
// TODO: move this somewhere else
|
||||
pub fn listener<T>(&self, fd_manager: &mut ListenFd) -> Result<T, anyhow::Error>
|
||||
where
|
||||
T: TryFrom<TcpListener> + TryFrom<UnixListener>,
|
||||
<T as TryFrom<TcpListener>>::Error: std::error::Error + Sync + Send + 'static,
|
||||
<T as TryFrom<UnixListener>>::Error: std::error::Error + Sync + Send + 'static,
|
||||
{
|
||||
match self {
|
||||
BindConfig::Listen { host, port } => {
|
||||
let addrs = match host.as_deref() {
|
||||
Some(host) => (host, *port)
|
||||
.to_socket_addrs()
|
||||
.context("could not parse listener host")?
|
||||
.collect(),
|
||||
|
||||
None => vec![
|
||||
SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), *port),
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), *port),
|
||||
],
|
||||
};
|
||||
|
||||
let listener = TcpListener::bind(&addrs[..]).context("could not bind address")?;
|
||||
listener.set_nonblocking(true)?;
|
||||
Ok(listener.try_into()?)
|
||||
}
|
||||
|
||||
BindConfig::Address { address } => {
|
||||
let addr: SocketAddr = address
|
||||
.parse()
|
||||
.context("could not parse listener address")?;
|
||||
let listener = TcpListener::bind(addr).context("could not bind address")?;
|
||||
Ok(listener)
|
||||
listener.set_nonblocking(true)?;
|
||||
Ok(listener.try_into()?)
|
||||
}
|
||||
|
||||
BindConfig::FileDescriptor { fd } => {
|
||||
let listener = fd_manager
|
||||
.take_tcp_listener(fd)?
|
||||
.context("no listener found on file descriptor")?;
|
||||
// XXX: Do I need that?
|
||||
BindConfig::Unix { socket } => {
|
||||
let listener = UnixListener::bind(socket).context("could not bind socket")?;
|
||||
listener.set_nonblocking(true)?;
|
||||
Ok(listener)
|
||||
Ok(listener.try_into()?)
|
||||
}
|
||||
|
||||
BindConfig::FileDescriptor {
|
||||
fd,
|
||||
kind: UnixOrTcp::Tcp,
|
||||
} => {
|
||||
let listener = fd_manager
|
||||
.take_tcp_listener(*fd)?
|
||||
.context("no listener found on file descriptor")?;
|
||||
listener.set_nonblocking(true)?;
|
||||
Ok(listener.try_into()?)
|
||||
}
|
||||
|
||||
BindConfig::FileDescriptor {
|
||||
fd,
|
||||
kind: UnixOrTcp::Unix,
|
||||
} => {
|
||||
let listener = fd_manager
|
||||
.take_unix_listener(*fd)?
|
||||
.context("no unix socket found on file descriptor")?;
|
||||
listener.set_nonblocking(true)?;
|
||||
Ok(listener.try_into()?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum KeyOrFile {
|
||||
Key(String),
|
||||
KeyFile(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CertificateOrFile {
|
||||
Certificate(String),
|
||||
CertificateFile(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
|
||||
pub struct TlsConfig {
|
||||
#[serde(flatten)]
|
||||
pub certificate: CertificateOrFile,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub key: KeyOrFile,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub password: Option<PasswordOrFile>,
|
||||
}
|
||||
|
||||
impl TlsConfig {
|
||||
pub async fn load(&self) -> Result<(Vec<u8>, Vec<Vec<u8>>), anyhow::Error> {
|
||||
let password = match &self.password {
|
||||
Some(PasswordOrFile::Password(password)) => Some(Cow::Borrowed(password.as_str())),
|
||||
Some(PasswordOrFile::PasswordFile(path)) => {
|
||||
Some(Cow::Owned(tokio::fs::read_to_string(path).await?))
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
// Read the key either embedded in the config file or on disk
|
||||
let key = match &self.key {
|
||||
KeyOrFile::Key(key) => {
|
||||
// If the key was embedded in the config file, assume it is formatted as PEM
|
||||
if let Some(password) = password {
|
||||
PrivateKey::load_encrypted_pem(key, password.as_bytes())?
|
||||
} else {
|
||||
PrivateKey::load_pem(key)?
|
||||
}
|
||||
}
|
||||
KeyOrFile::KeyFile(path) => {
|
||||
// When reading from disk, it might be either PEM or DER. `PrivateKey::load*`
|
||||
// will try both.
|
||||
let key = tokio::fs::read(path).await?;
|
||||
if let Some(password) = password {
|
||||
PrivateKey::load_encrypted(&key, password.as_bytes())?
|
||||
} else {
|
||||
PrivateKey::load(&key)?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Re-serialize the key to PKCS#8 DER, so rustls can consume it
|
||||
let key = key.to_pkcs8_der()?;
|
||||
// This extracts the Vec out of the Zeroizing by copying it
|
||||
// XXX: maybe we should keep that zeroizing?
|
||||
let key = key.deref().clone();
|
||||
|
||||
let certificate_chain_pem = match &self.certificate {
|
||||
CertificateOrFile::Certificate(pem) => Cow::Borrowed(pem.as_str()),
|
||||
CertificateOrFile::CertificateFile(path) => {
|
||||
Cow::Owned(tokio::fs::read_to_string(path).await?)
|
||||
}
|
||||
};
|
||||
|
||||
let mut certificate_chain_reader = Cursor::new(certificate_chain_pem.as_bytes());
|
||||
let certificate_chain = rustls_pemfile::certs(&mut certificate_chain_reader)?;
|
||||
|
||||
if certificate_chain.is_empty() {
|
||||
bail!("TLS certificate chain is empty (or invalid)")
|
||||
}
|
||||
|
||||
Ok((key, certificate_chain))
|
||||
}
|
||||
}
|
||||
|
||||
/// HTTP resources to mount
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
|
||||
#[serde(tag = "name", rename_all = "lowercase")]
|
||||
pub enum Resource {
|
||||
/// Healthcheck endpoint (/health)
|
||||
Health,
|
||||
|
||||
/// OIDC discovery endpoints
|
||||
Discovery,
|
||||
|
||||
/// Pages destined to be viewed by humans
|
||||
Human,
|
||||
|
||||
/// OAuth-related APIs
|
||||
OAuth,
|
||||
|
||||
/// Matrix compatibility API
|
||||
Compat,
|
||||
|
||||
/// Static files
|
||||
Static,
|
||||
}
|
||||
|
||||
/// Configuration of a listener
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
|
||||
pub struct ListenerConfig {
|
||||
pub name: Option<String>,
|
||||
/// List of resources to mount
|
||||
pub resources: Vec<Resource>,
|
||||
|
||||
/// List of sockets to bind
|
||||
pub binds: Vec<BindConfig>,
|
||||
|
||||
/// If set, makes the listener use TLS with the provided certificate and key
|
||||
pub tls: Option<TlsConfig>,
|
||||
}
|
||||
|
||||
/// Configuration related to the web server
|
||||
@ -114,12 +300,28 @@ impl Default for HttpConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
web_root: None,
|
||||
listeners: vec![ListenerConfig {
|
||||
name: None,
|
||||
listeners: vec![
|
||||
ListenerConfig {
|
||||
resources: vec![
|
||||
Resource::Discovery,
|
||||
Resource::Human,
|
||||
Resource::OAuth,
|
||||
Resource::Compat,
|
||||
Resource::Static,
|
||||
],
|
||||
tls: None,
|
||||
binds: vec![BindConfig::Address {
|
||||
address: default_http_address(),
|
||||
address: "[::]:8080".into(),
|
||||
}],
|
||||
},
|
||||
ListenerConfig {
|
||||
resources: vec![Resource::Health],
|
||||
tls: None,
|
||||
binds: vec![BindConfig::Address {
|
||||
address: "localhost:8081".into(),
|
||||
}],
|
||||
},
|
||||
],
|
||||
public_base: default_public_base(),
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ pub use self::{
|
||||
csrf::CsrfConfig,
|
||||
database::DatabaseConfig,
|
||||
email::{EmailConfig, EmailSmtpMode, EmailTransportConfig},
|
||||
http::HttpConfig,
|
||||
http::{HttpConfig, Resource as HttpResource},
|
||||
matrix::MatrixConfig,
|
||||
policy::PolicyConfig,
|
||||
secrets::SecretsConfig,
|
||||
|
@ -50,6 +50,57 @@ pub use compat::MatrixHomeserver;
|
||||
|
||||
pub use self::app_state::AppState;
|
||||
|
||||
#[must_use]
|
||||
pub fn empty_router<S, B>(state: Arc<S>) -> Router<S, B>
|
||||
where
|
||||
B: HttpBody + Send + 'static,
|
||||
S: Send + Sync + 'static,
|
||||
{
|
||||
Router::with_state_arc(state)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn healthcheck_router<S, B>(state: Arc<S>) -> Router<S, B>
|
||||
where
|
||||
B: HttpBody + Send + 'static,
|
||||
S: Send + Sync + 'static,
|
||||
PgPool: FromRef<S>,
|
||||
{
|
||||
Router::with_state_arc(state).route(mas_router::Healthcheck::route(), get(self::health::get))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn discovery_router<S, B>(state: Arc<S>) -> Router<S, B>
|
||||
where
|
||||
B: HttpBody + Send + 'static,
|
||||
S: Send + Sync + 'static,
|
||||
Keystore: FromRef<S>,
|
||||
UrlBuilder: FromRef<S>,
|
||||
{
|
||||
Router::with_state_arc(state)
|
||||
.route(
|
||||
mas_router::OidcConfiguration::route(),
|
||||
get(self::oauth2::discovery::get),
|
||||
)
|
||||
.route(
|
||||
mas_router::Webfinger::route(),
|
||||
get(self::oauth2::webfinger::get),
|
||||
)
|
||||
.layer(
|
||||
CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods(Any)
|
||||
.allow_otel_headers([
|
||||
AUTHORIZATION,
|
||||
ACCEPT,
|
||||
ACCEPT_LANGUAGE,
|
||||
CONTENT_LANGUAGE,
|
||||
CONTENT_TYPE,
|
||||
])
|
||||
.max_age(Duration::from_secs(60 * 60)),
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::trait_duplication_in_bounds)]
|
||||
pub fn api_router<S, B>(state: Arc<S>) -> Router<S, B>
|
||||
@ -66,19 +117,6 @@ where
|
||||
{
|
||||
// All those routes are API-like, with a common CORS layer
|
||||
Router::with_state_arc(state)
|
||||
.route(mas_router::Healthcheck::route(), get(self::health::get))
|
||||
.route(
|
||||
mas_router::ChangePasswordDiscovery::route(),
|
||||
get(|| async { mas_router::AccountPassword.go() }),
|
||||
)
|
||||
.route(
|
||||
mas_router::OidcConfiguration::route(),
|
||||
get(self::oauth2::discovery::get),
|
||||
)
|
||||
.route(
|
||||
mas_router::Webfinger::route(),
|
||||
get(self::oauth2::webfinger::get),
|
||||
)
|
||||
.route(
|
||||
mas_router::OAuth2Keys::route(),
|
||||
get(self::oauth2::keys::get),
|
||||
@ -116,6 +154,7 @@ where
|
||||
.max_age(Duration::from_secs(60 * 60)),
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::trait_duplication_in_bounds)]
|
||||
pub fn compat_router<S, B>(state: Arc<S>) -> Router<S, B>
|
||||
@ -174,6 +213,10 @@ where
|
||||
{
|
||||
let templates = Templates::from_ref(&state);
|
||||
Router::with_state_arc(state)
|
||||
.route(
|
||||
mas_router::ChangePasswordDiscovery::route(),
|
||||
get(|| async { mas_router::AccountPassword.go() }),
|
||||
)
|
||||
.route(mas_router::Index::route(), get(self::views::index::get))
|
||||
.route(
|
||||
mas_router::Login::route(),
|
||||
@ -267,11 +310,18 @@ where
|
||||
Mailer: FromRef<S>,
|
||||
MatrixHomeserver: FromRef<S>,
|
||||
{
|
||||
let healthcheck_router = healthcheck_router(state.clone());
|
||||
let discovery_router = discovery_router(state.clone());
|
||||
let api_router = api_router(state.clone());
|
||||
let compat_router = compat_router(state.clone());
|
||||
let human_router = human_router(state);
|
||||
let human_router = human_router(state.clone());
|
||||
|
||||
human_router.merge(api_router).merge(compat_router)
|
||||
Router::with_state_arc(state)
|
||||
.merge(healthcheck_router)
|
||||
.merge(discovery_router)
|
||||
.merge(human_router)
|
||||
.merge(api_router)
|
||||
.merge(compat_router)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -26,6 +26,7 @@
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use der::{zeroize::Zeroizing, Decode};
|
||||
use elliptic_curve::pkcs8::EncodePrivateKey;
|
||||
use mas_iana::jose::{JsonWebKeyType, JsonWebSignatureAlg};
|
||||
pub use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
|
||||
use mas_jose::{
|
||||
@ -213,6 +214,22 @@ impl PrivateKey {
|
||||
Ok(der)
|
||||
}
|
||||
|
||||
/// Serialize the key as a PKCS8 DER document
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the encoding failed
|
||||
pub fn to_pkcs8_der(&self) -> Result<Zeroizing<Vec<u8>>, anyhow::Error> {
|
||||
let der = match self {
|
||||
PrivateKey::Rsa(key) => key.to_pkcs8_der()?,
|
||||
PrivateKey::EcP256(key) => key.to_pkcs8_der()?,
|
||||
PrivateKey::EcP384(key) => key.to_pkcs8_der()?,
|
||||
PrivateKey::EcK256(key) => key.to_pkcs8_der()?,
|
||||
};
|
||||
|
||||
Ok(der.to_bytes())
|
||||
}
|
||||
|
||||
/// Serialize the key as a PEM document
|
||||
///
|
||||
/// It will use the most common format depending on the key type: PKCS1 for
|
||||
|
14
crates/listener/Cargo.toml
Normal file
14
crates/listener/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "mas-listener"
|
||||
version = "0.1.0"
|
||||
authors = ["Quentin Gliech <quenting@element.io>"]
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.21.2", features = ["net"] }
|
||||
pin-project-lite = "0.2.9"
|
||||
hyper = { version = "0.14.20", features = ["server"] }
|
||||
futures-util = "0.3.24"
|
||||
tracing = "0.1.36"
|
||||
tokio-rustls = "0.23.4"
|
16
crates/listener/src/lib.rs
Normal file
16
crates/listener/src/lib.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub mod maybe_tls;
|
||||
pub mod unix_or_tcp;
|
213
crates/listener/src/maybe_tls.rs
Normal file
213
crates/listener/src/maybe_tls.rs
Normal file
@ -0,0 +1,213 @@
|
||||
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::{
|
||||
ops::Deref,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{ready, Context, Poll},
|
||||
};
|
||||
|
||||
use futures_util::Future;
|
||||
use hyper::server::accept::Accept;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use tokio_rustls::rustls::{ServerConfig, ServerConnection};
|
||||
|
||||
pub enum MaybeTlsStream<T> {
|
||||
Handshaking(tokio_rustls::Accept<T>),
|
||||
Streaming(tokio_rustls::server::TlsStream<T>),
|
||||
Insecure(T),
|
||||
}
|
||||
|
||||
impl<T> MaybeTlsStream<T> {
|
||||
pub fn new(stream: T, config: Option<Arc<ServerConfig>>) -> Self
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
if let Some(config) = config {
|
||||
let accept = tokio_rustls::TlsAcceptor::from(config).accept(stream);
|
||||
MaybeTlsStream::Handshaking(accept)
|
||||
} else {
|
||||
MaybeTlsStream::Insecure(stream)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying IO stream
|
||||
///
|
||||
/// Returns [`None`] if the stream closed before the TLS handshake finished.
|
||||
/// It is guaranteed to return [`Some`] value after the handshake finished,
|
||||
/// or if it is a non-TLS connection.
|
||||
pub fn get_ref(&self) -> Option<&T> {
|
||||
match self {
|
||||
Self::Handshaking(accept) => accept.get_ref(),
|
||||
Self::Streaming(stream) => {
|
||||
let (inner, _) = stream.get_ref();
|
||||
Some(inner)
|
||||
}
|
||||
Self::Insecure(inner) => Some(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a ref to the [`ServerConnection`] of the establish TLS stream.
|
||||
///
|
||||
/// Returns [`None`] if the connection is still handshaking and for non-TLS
|
||||
/// connections.
|
||||
pub fn get_tls_connection(&self) -> Option<&ServerConnection> {
|
||||
match self {
|
||||
Self::Streaming(stream) => {
|
||||
let (_, conn) = stream.get_ref();
|
||||
Some(conn)
|
||||
}
|
||||
Self::Handshaking(_) | Self::Insecure(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncRead for MaybeTlsStream<T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
buf: &mut ReadBuf,
|
||||
) -> Poll<std::io::Result<()>> {
|
||||
let pin = self.get_mut();
|
||||
match pin {
|
||||
MaybeTlsStream::Handshaking(ref mut accept) => {
|
||||
match ready!(Pin::new(accept).poll(cx)) {
|
||||
Ok(mut stream) => {
|
||||
let result = Pin::new(&mut stream).poll_read(cx, buf);
|
||||
*pin = MaybeTlsStream::Streaming(stream);
|
||||
result
|
||||
}
|
||||
Err(err) => Poll::Ready(Err(err)),
|
||||
}
|
||||
}
|
||||
MaybeTlsStream::Streaming(ref mut stream) => Pin::new(stream).poll_read(cx, buf),
|
||||
MaybeTlsStream::Insecure(ref mut stream) => Pin::new(stream).poll_read(cx, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncWrite for MaybeTlsStream<T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<std::io::Result<usize>> {
|
||||
let pin = self.get_mut();
|
||||
match pin {
|
||||
MaybeTlsStream::Handshaking(ref mut accept) => {
|
||||
match ready!(Pin::new(accept).poll(cx)) {
|
||||
Ok(mut stream) => {
|
||||
let result = Pin::new(&mut stream).poll_write(cx, buf);
|
||||
*pin = MaybeTlsStream::Streaming(stream);
|
||||
result
|
||||
}
|
||||
Err(err) => Poll::Ready(Err(err)),
|
||||
}
|
||||
}
|
||||
MaybeTlsStream::Streaming(ref mut stream) => Pin::new(stream).poll_write(cx, buf),
|
||||
MaybeTlsStream::Insecure(ref mut fallback) => Pin::new(fallback).poll_write(cx, buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
match self.get_mut() {
|
||||
MaybeTlsStream::Handshaking { .. } => Poll::Ready(Ok(())),
|
||||
MaybeTlsStream::Streaming(ref mut stream) => Pin::new(stream).poll_flush(cx),
|
||||
MaybeTlsStream::Insecure(ref mut stream) => Pin::new(stream).poll_flush(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
match self.get_mut() {
|
||||
MaybeTlsStream::Handshaking { .. } => Poll::Ready(Ok(())),
|
||||
MaybeTlsStream::Streaming(ref mut stream) => Pin::new(stream).poll_shutdown(cx),
|
||||
MaybeTlsStream::Insecure(ref mut stream) => Pin::new(stream).poll_shutdown(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MaybeTlsAcceptor<T> {
|
||||
tls_config: Option<Arc<ServerConfig>>,
|
||||
incoming: T,
|
||||
}
|
||||
|
||||
impl<T> MaybeTlsAcceptor<T> {
|
||||
pub fn new(tls_config: Option<Arc<ServerConfig>>, incoming: T) -> Self {
|
||||
Self {
|
||||
tls_config,
|
||||
incoming,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_secure(tls_config: Arc<ServerConfig>, incoming: T) -> Self {
|
||||
Self {
|
||||
tls_config: Some(tls_config),
|
||||
incoming,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_insecure(incoming: T) -> Self {
|
||||
Self {
|
||||
tls_config: None,
|
||||
incoming,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn is_secure(&self) -> bool {
|
||||
self.tls_config.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Accept for MaybeTlsAcceptor<T>
|
||||
where
|
||||
T: Accept + Unpin,
|
||||
T::Conn: AsyncRead + AsyncWrite + Unpin,
|
||||
T::Error: Into<std::io::Error>,
|
||||
{
|
||||
type Conn = MaybeTlsStream<T::Conn>;
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn poll_accept(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
|
||||
let pin = self.get_mut();
|
||||
|
||||
let ret = match ready!(Pin::new(&mut pin.incoming).poll_accept(cx)) {
|
||||
Some(Ok(sock)) => {
|
||||
let config = pin.tls_config.clone();
|
||||
Some(Ok(MaybeTlsStream::new(sock, config)))
|
||||
}
|
||||
|
||||
Some(Err(e)) => Some(Err(e.into())),
|
||||
None => None,
|
||||
};
|
||||
|
||||
Poll::Ready(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for MaybeTlsAcceptor<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.incoming
|
||||
}
|
||||
}
|
212
crates/listener/src/unix_or_tcp.rs
Normal file
212
crates/listener/src/unix_or_tcp.rs
Normal file
@ -0,0 +1,212 @@
|
||||
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// TODO: Unlink the UNIX socket on drop?
|
||||
// TODO: Proxy protocol
|
||||
|
||||
use std::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use futures_util::ready;
|
||||
use hyper::server::accept::Accept;
|
||||
use tokio::{
|
||||
io::{AsyncRead, AsyncWrite},
|
||||
net::{TcpListener, TcpStream, UnixListener, UnixStream},
|
||||
};
|
||||
|
||||
pub enum SocketAddr {
|
||||
Unix(tokio::net::unix::SocketAddr),
|
||||
Net(std::net::SocketAddr),
|
||||
}
|
||||
|
||||
impl From<tokio::net::unix::SocketAddr> for SocketAddr {
|
||||
fn from(value: tokio::net::unix::SocketAddr) -> Self {
|
||||
Self::Unix(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::net::SocketAddr> for SocketAddr {
|
||||
fn from(value: std::net::SocketAddr) -> Self {
|
||||
Self::Net(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SocketAddr {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Unix(l) => std::fmt::Debug::fmt(l, f),
|
||||
Self::Net(l) => std::fmt::Debug::fmt(l, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum UnixOrTcpListener {
|
||||
Unix(UnixListener),
|
||||
Tcp(TcpListener),
|
||||
}
|
||||
|
||||
impl From<UnixListener> for UnixOrTcpListener {
|
||||
fn from(listener: UnixListener) -> Self {
|
||||
Self::Unix(listener)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TcpListener> for UnixOrTcpListener {
|
||||
fn from(listener: TcpListener) -> Self {
|
||||
Self::Tcp(listener)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<std::os::unix::net::UnixListener> for UnixOrTcpListener {
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(listener: std::os::unix::net::UnixListener) -> Result<Self, Self::Error> {
|
||||
Ok(Self::Unix(UnixListener::from_std(listener)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<std::net::TcpListener> for UnixOrTcpListener {
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(listener: std::net::TcpListener) -> Result<Self, Self::Error> {
|
||||
Ok(Self::Tcp(TcpListener::from_std(listener)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl UnixOrTcpListener {
|
||||
pub fn local_addr(&self) -> Result<SocketAddr, std::io::Error> {
|
||||
match self {
|
||||
Self::Unix(listener) => listener.local_addr().map(SocketAddr::from),
|
||||
Self::Tcp(listener) => listener.local_addr().map(SocketAddr::from),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_project_lite::pin_project! {
|
||||
#[project = UnixOrTcpConnectionProj]
|
||||
pub enum UnixOrTcpConnection {
|
||||
Unix {
|
||||
#[pin]
|
||||
stream: UnixStream,
|
||||
},
|
||||
|
||||
Tcp {
|
||||
#[pin]
|
||||
stream: TcpStream,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
impl UnixOrTcpConnection {
|
||||
pub fn local_addr(&self) -> Result<SocketAddr, std::io::Error> {
|
||||
match self {
|
||||
Self::Unix { stream, .. } => stream.local_addr().map(SocketAddr::from),
|
||||
Self::Tcp { stream, .. } => stream.local_addr().map(SocketAddr::from),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> Result<SocketAddr, std::io::Error> {
|
||||
match self {
|
||||
Self::Unix { stream, .. } => stream.peer_addr().map(SocketAddr::from),
|
||||
Self::Tcp { stream, .. } => stream.peer_addr().map(SocketAddr::from),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Accept for UnixOrTcpListener {
|
||||
type Error = std::io::Error;
|
||||
type Conn = UnixOrTcpConnection;
|
||||
|
||||
fn poll_accept(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> std::task::Poll<Option<Result<Self::Conn, Self::Error>>> {
|
||||
let conn = match &*self {
|
||||
Self::Unix(listener) => {
|
||||
let (stream, _remote_addr) = ready!(listener.poll_accept(cx))?;
|
||||
UnixOrTcpConnection::Unix { stream }
|
||||
}
|
||||
|
||||
Self::Tcp(listener) => {
|
||||
let (stream, _remote_addr) = ready!(listener.poll_accept(cx))?;
|
||||
UnixOrTcpConnection::Tcp { stream }
|
||||
}
|
||||
};
|
||||
|
||||
Poll::Ready(Some(Ok(conn)))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for UnixOrTcpConnection {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut tokio::io::ReadBuf<'_>,
|
||||
) -> Poll<std::io::Result<()>> {
|
||||
match self.project() {
|
||||
UnixOrTcpConnectionProj::Unix { stream } => stream.poll_read(cx, buf),
|
||||
UnixOrTcpConnectionProj::Tcp { stream } => stream.poll_read(cx, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for UnixOrTcpConnection {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, std::io::Error>> {
|
||||
match self.project() {
|
||||
UnixOrTcpConnectionProj::Unix { stream } => stream.poll_write(cx, buf),
|
||||
UnixOrTcpConnectionProj::Tcp { stream } => stream.poll_write(cx, buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
|
||||
match self.project() {
|
||||
UnixOrTcpConnectionProj::Unix { stream } => stream.poll_flush(cx),
|
||||
UnixOrTcpConnectionProj::Tcp { stream } => stream.poll_flush(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_shutdown(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), std::io::Error>> {
|
||||
match self.project() {
|
||||
UnixOrTcpConnectionProj::Unix { stream } => stream.poll_shutdown(cx),
|
||||
UnixOrTcpConnectionProj::Tcp { stream } => stream.poll_shutdown(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[std::io::IoSlice<'_>],
|
||||
) -> Poll<Result<usize, std::io::Error>> {
|
||||
match self.project() {
|
||||
UnixOrTcpConnectionProj::Unix { stream } => stream.poll_write_vectored(cx, bufs),
|
||||
UnixOrTcpConnectionProj::Tcp { stream } => stream.poll_write_vectored(cx, bufs),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
match self {
|
||||
UnixOrTcpConnection::Unix { stream } => stream.is_write_vectored(),
|
||||
UnixOrTcpConnection::Tcp { stream } => stream.is_write_vectored(),
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user