diff --git a/Cargo.toml b/Cargo.toml index 6fca3c4e..4d016e3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,12 +59,12 @@ proxmox-async = "0.4" proxmox-borrow = "1" proxmox-compression = "0.1.1" proxmox-fuse = "0.1.3" -proxmox-http = { version = "0.7", features = [ "client", "http-helpers", "websocket" ] } # see below +proxmox-http = { version = "0.8.0", features = [ "client", "http-helpers", "websocket" ] } # see below proxmox-io = "1.0.1" # tools and client use "tokio" feature proxmox-lang = "1.1" proxmox-ldap = "0.1" proxmox-metrics = "0.2" -proxmox-rest-server = "0.2.2" +proxmox-rest-server = { version = "0.3.0", features = [ "templates" ] } # some use "cli", some use "cli" and "server", pbs-config uses nothing proxmox-router = { version = "1.3.1", default_features = false } # everything but pbs-config and pbs-client ues "api-macro" @@ -204,12 +204,12 @@ zstd.workspace = true proxmox-async.workspace = true proxmox-compression.workspace = true -proxmox-http = { workspace = true, features = [ "client-trait", "proxmox-async" ] } # pbs-client doesn't use these +proxmox-http = { workspace = true, features = [ "client-trait", "proxmox-async", "rate-limited-stream" ] } # pbs-client doesn't use these proxmox-io.workspace = true proxmox-lang.workspace = true proxmox-ldap.workspace = true proxmox-metrics.workspace = true -proxmox-rest-server.workspace = true +proxmox-rest-server = { workspace = true, features = [ "rate-limited-stream" ] } proxmox-router = { workspace = true, features = [ "cli", "server"] } proxmox-schema = { workspace = true, features = [ "api-macro" ] } proxmox-section-config.workspace = true @@ -243,25 +243,28 @@ proxmox-rrd.workspace = true # NOTE: You must run `cargo update` after changing this for it to take effect! [patch.crates-io] #proxmox-acme-rs = { path = "../proxmox-acme-rs" } -#proxmox-apt = { path = "../proxmox-apt" } #proxmox-async = { path = "../proxmox/proxmox-async" } -#proxmox-compression = { path = "../proxmox/proxmox-compression" } #proxmox-borrow = { path = "../proxmox/proxmox-borrow" } +#proxmox-compression = { path = "../proxmox/proxmox-compression" } #proxmox-fuse = { path = "../proxmox-fuse" } #proxmox-http = { path = "../proxmox/proxmox-http" } #proxmox-io = { path = "../proxmox/proxmox-io" } #proxmox-lang = { path = "../proxmox/proxmox-lang" } -#proxmox-openid = { path = "../proxmox-openid-rs" } -#proxmox-router = { path = "../proxmox/proxmox-rest-server" } +#proxmox-rest-server = { path = "../proxmox/proxmox-rest-server" } #proxmox-router = { path = "../proxmox/proxmox-router" } #proxmox-schema = { path = "../proxmox/proxmox-schema" } #proxmox-section-config = { path = "../proxmox/proxmox-section-config" } -#proxmox-shared-memory = { path = "../proxmox/proxmox-shared-memory" } -#proxmox-sys = { path = "../proxmox/proxmox-sys" } #proxmox-serde = { path = "../proxmox/proxmox-serde" } +#proxmox-shared-memory = { path = "../proxmox/proxmox-shared-memory" } +#proxmox-subscription = { path = "../proxmox/proxmox-subscription" } +#proxmox-sys = { path = "../proxmox/proxmox-sys" } #proxmox-tfa = { path = "../proxmox/proxmox-tfa" } #proxmox-time = { path = "../proxmox/proxmox-time" } #proxmox-uuid = { path = "../proxmox/proxmox-uuid" } + +#proxmox-apt = { path = "../proxmox-apt" } +#proxmox-openid = { path = "../proxmox-openid-rs" } + #pxar = { path = "../pxar" } [features] diff --git a/debian/control b/debian/control index ad0b16ab..80a786af 100644 --- a/debian/control +++ b/debian/control @@ -47,19 +47,23 @@ Build-Depends: debhelper (>= 12), librust-proxmox-borrow-1+default-dev, librust-proxmox-compression-0.1+default-dev (>= 0.1.1-~~), librust-proxmox-fuse-0.1+default-dev (>= 0.1.3-~~), - librust-proxmox-http-0.7+client-dev, - librust-proxmox-http-0.7+client-trait-dev, - librust-proxmox-http-0.7+default-dev, - librust-proxmox-http-0.7+http-helpers-dev, - librust-proxmox-http-0.7+proxmox-async-dev, - librust-proxmox-http-0.7+websocket-dev, + librust-proxmox-http-0.8+client-dev, + librust-proxmox-http-0.8+client-trait-dev, + librust-proxmox-http-0.8+default-dev, + librust-proxmox-http-0.8+http-helpers-dev, + librust-proxmox-http-0.8+proxmox-async-dev, + librust-proxmox-http-0.8+rate-limited-stream-dev, + librust-proxmox-http-0.8+rate-limiter-dev, + librust-proxmox-http-0.8+websocket-dev, librust-proxmox-io-1+default-dev (>= 1.0.1-~~), librust-proxmox-io-1+tokio-dev (>= 1.0.1-~~), librust-proxmox-lang-1+default-dev (>= 1.1-~~), librust-proxmox-ldap-0.1+default-dev, librust-proxmox-metrics-0.2+default-dev, librust-proxmox-openid-0.9+default-dev (>= 0.9.9-~~), - librust-proxmox-rest-server-0.2+default-dev (>= 0.2.2-~~), + librust-proxmox-rest-server-0.3+default-dev, + librust-proxmox-rest-server-0.3+rate-limited-stream-dev, + librust-proxmox-rest-server-0.3+templates-dev, librust-proxmox-router-1+cli-dev (>= 1.3.1-~~), librust-proxmox-router-1+default-dev (>= 1.3.1-~~), librust-proxmox-router-1+server-dev (>= 1.3.1-~~), diff --git a/pbs-client/Cargo.toml b/pbs-client/Cargo.toml index 4bae79d6..dd22e7a0 100644 --- a/pbs-client/Cargo.toml +++ b/pbs-client/Cargo.toml @@ -35,7 +35,7 @@ pathpatterns.workspace = true proxmox-async.workspace = true proxmox-compression.workspace = true -proxmox-http.workspace = true +proxmox-http = { workspace = true, features = [ "rate-limiter" ] } proxmox-io = { workspace = true, features = [ "tokio" ] } proxmox-lang.workspace = true proxmox-router = { workspace = true, features = [ "cli", "server" ] } diff --git a/pbs-client/src/http_client.rs b/pbs-client/src/http_client.rs index d9f6b7af..4c1f7919 100644 --- a/pbs-client/src/http_client.rs +++ b/pbs-client/src/http_client.rs @@ -22,9 +22,9 @@ use proxmox_sys::fs::{file_get_json, replace_file, CreateOptions}; use proxmox_sys::linux::tty; use proxmox_async::broadcast_future::BroadcastFuture; -use proxmox_http::client::{HttpsConnector, RateLimiter}; +use proxmox_http::client::HttpsConnector; use proxmox_http::uri::{build_authority, json_object_to_query}; -use proxmox_http::ProxyConfig; +use proxmox_http::{ProxyConfig, RateLimiter}; use pbs_api_types::percent_encoding::DEFAULT_ENCODE_SET; use pbs_api_types::{Authid, RateLimitConfig, Userid}; diff --git a/proxmox-restore-daemon/src/main.rs b/proxmox-restore-daemon/src/main.rs index f7b94ef1..f94b6c67 100644 --- a/proxmox-restore-daemon/src/main.rs +++ b/proxmox-restore-daemon/src/main.rs @@ -107,10 +107,13 @@ async fn run() -> Result<(), Error> { } }; - let adaptor = StaticAuthAdapter::new() - .map_err(|err| format_err!("reading ticket file failed: {}", err))?; + let ticket = + auth::read_ticket().map_err(|err| format_err!("reading ticket file failed: {}", err))?; - let config = ApiConfig::new("", &ROUTER, RpcEnvironmentType::PUBLIC, adaptor)?; + let config = ApiConfig::new("", RpcEnvironmentType::PUBLIC) + .default_api2_handler(&ROUTER) + .index_handler_func(|_, _| auth::get_index()) + .auth_handler_func(move |h, m| Box::pin(auth::check_auth(Arc::clone(&ticket), h, m))); let rest_server = RestServer::new(config); let vsock_fd = get_vsock_fd()?; diff --git a/proxmox-restore-daemon/src/proxmox_restore_daemon/auth.rs b/proxmox-restore-daemon/src/proxmox_restore_daemon/auth.rs index 70475085..e0eeca17 100644 --- a/proxmox-restore-daemon/src/proxmox_restore_daemon/auth.rs +++ b/proxmox-restore-daemon/src/proxmox_restore_daemon/auth.rs @@ -3,15 +3,15 @@ use std::fs::File; use std::future::Future; use std::io::prelude::*; use std::pin::Pin; +use std::sync::Arc; use anyhow::{bail, format_err, Error}; -use http::request::Parts; use http::HeaderMap; use hyper::{Body, Method, Response, StatusCode}; use proxmox_router::UserInformation; -use proxmox_rest_server::{AuthError, RestEnvironment, ServerAdapter}; +use proxmox_rest_server::AuthError; const TICKET_FILE: &str = "/ticket"; @@ -29,61 +29,49 @@ impl UserInformation for SimpleUserInformation { } } -pub struct StaticAuthAdapter { - ticket: String, -} - -impl StaticAuthAdapter { - pub fn new() -> Result { - let mut ticket_file = File::open(TICKET_FILE)?; - let mut ticket = String::new(); - let len = ticket_file.read_to_string(&mut ticket)?; - if len == 0 { - bail!("invalid ticket: cannot be empty"); - } - Ok(StaticAuthAdapter { ticket }) +pub fn read_ticket() -> Result, Error> { + let mut ticket_file = File::open(TICKET_FILE)?; + let mut ticket = String::new(); + let len = ticket_file.read_to_string(&mut ticket)?; + if len == 0 { + bail!("invalid ticket: cannot be empty"); } + Ok(ticket.into()) } -impl ServerAdapter for StaticAuthAdapter { - fn check_auth<'a>( - &'a self, - headers: &'a HeaderMap, - _method: &'a Method, - ) -> Pin< - Box< - dyn Future), AuthError>> - + Send - + 'a, - >, - > { - Box::pin(async move { - match headers.get(hyper::header::AUTHORIZATION) { - Some(header) if header.to_str().unwrap_or("") == self.ticket => { - let user_info: Box = - Box::new(SimpleUserInformation {}); - Ok((String::from("root@pam"), user_info)) - } - _ => Err(AuthError::Generic(format_err!( - "invalid file restore ticket provided" - ))), +pub fn check_auth<'a>( + ticket: Arc, + headers: &'a HeaderMap, + _method: &'a Method, +) -> Pin< + Box< + dyn Future), AuthError>> + + Send + + 'a, + >, +> { + Box::pin(async move { + match headers.get(hyper::header::AUTHORIZATION) { + Some(header) if header.to_str().unwrap_or("") == &*ticket => { + let user_info: Box = + Box::new(SimpleUserInformation {}); + Ok((String::from("root@pam"), user_info)) } - }) - } - - fn get_index( - &self, - _env: RestEnvironment, - _parts: Parts, - ) -> Pin> + Send>> { - Box::pin(async move { - let index = "

Proxmox Backup Restore Daemon/h1>

"; - - Response::builder() - .status(StatusCode::OK) - .header(hyper::header::CONTENT_TYPE, "text/html") - .body(index.into()) - .unwrap() - }) - } + _ => Err(AuthError::Generic(format_err!( + "invalid file restore ticket provided" + ))), + } + }) +} + +pub fn get_index() -> Pin> + Send>> { + Box::pin(async move { + let index = "

Proxmox Backup Restore Daemon/h1>

"; + + Response::builder() + .status(StatusCode::OK) + .header(hyper::header::CONTENT_TYPE, "text/html") + .body(index.into()) + .unwrap() + }) } diff --git a/src/bin/proxmox-backup-api.rs b/src/bin/proxmox-backup-api.rs index 441b3427..4de31ca7 100644 --- a/src/bin/proxmox-backup-api.rs +++ b/src/bin/proxmox-backup-api.rs @@ -3,18 +3,14 @@ use std::pin::Pin; use anyhow::{bail, Error}; use futures::*; -use http::request::Parts; -use http::HeaderMap; use http::Response; -use hyper::{Body, Method, StatusCode}; +use hyper::{Body, StatusCode}; use proxmox_lang::try_block; -use proxmox_router::{RpcEnvironmentType, UserInformation}; +use proxmox_router::RpcEnvironmentType; use proxmox_sys::fs::CreateOptions; -use proxmox_rest_server::{ - daemon, ApiConfig, AuthError, RestEnvironment, RestServer, ServerAdapter, -}; +use proxmox_rest_server::{daemon, ApiConfig, RestServer}; use proxmox_backup::auth_helpers::*; use proxmox_backup::config; @@ -31,38 +27,16 @@ fn main() { } } -struct ProxmoxBackupApiAdapter; +fn get_index() -> Pin> + Send>> { + Box::pin(async move { + let index = "

Proxmox Backup API Server

"; -impl ServerAdapter for ProxmoxBackupApiAdapter { - fn get_index( - &self, - _env: RestEnvironment, - _parts: Parts, - ) -> Pin> + Send>> { - Box::pin(async move { - let index = "

Proxmox Backup API Server

"; - - Response::builder() - .status(StatusCode::OK) - .header(hyper::header::CONTENT_TYPE, "text/html") - .body(index.into()) - .unwrap() - }) - } - - fn check_auth<'a>( - &'a self, - headers: &'a HeaderMap, - method: &'a Method, - ) -> Pin< - Box< - dyn Future), AuthError>> - + Send - + 'a, - >, - > { - Box::pin(async move { check_pbs_auth(headers, method).await }) - } + Response::builder() + .status(StatusCode::OK) + .header(hyper::header::CONTENT_TYPE, "text/html") + .body(index.into()) + .unwrap() + }) } async fn run() -> Result<(), Error> { @@ -97,13 +71,6 @@ async fn run() -> Result<(), Error> { } let _ = csrf_secret(); // load with lazy_static - let mut config = ApiConfig::new( - pbs_buildcfg::JS_DIR, - &proxmox_backup::api2::ROUTER, - RpcEnvironmentType::PRIVILEGED, - ProxmoxBackupApiAdapter, - )?; - let backup_user = pbs_config::backup_user()?; let mut commando_sock = proxmox_rest_server::CommandSocket::new( proxmox_rest_server::our_ctrl_sock(), @@ -117,19 +84,22 @@ async fn run() -> Result<(), Error> { .owner(backup_user.uid) .group(backup_user.gid); - config.enable_access_log( - pbs_buildcfg::API_ACCESS_LOG_FN, - Some(dir_opts.clone()), - Some(file_opts.clone()), - &mut commando_sock, - )?; - - config.enable_auth_log( - pbs_buildcfg::API_AUTH_LOG_FN, - Some(dir_opts.clone()), - Some(file_opts.clone()), - &mut commando_sock, - )?; + let config = ApiConfig::new(pbs_buildcfg::JS_DIR, RpcEnvironmentType::PRIVILEGED) + .index_handler_func(|_, _| get_index()) + .auth_handler_func(|h, m| Box::pin(check_pbs_auth(h, m))) + .default_api2_handler(&proxmox_backup::api2::ROUTER) + .enable_access_log( + pbs_buildcfg::API_ACCESS_LOG_FN, + Some(dir_opts.clone()), + Some(file_opts.clone()), + &mut commando_sock, + )? + .enable_auth_log( + pbs_buildcfg::API_AUTH_LOG_FN, + Some(dir_opts.clone()), + Some(file_opts.clone()), + &mut commando_sock, + )?; let rest_server = RestServer::new(config); proxmox_rest_server::init_worker_tasks( diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 0f192012..026f90c9 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -1,7 +1,4 @@ -use std::future::Future; -use std::os::unix::io::AsRawFd; use std::path::{Path, PathBuf}; -use std::pin::Pin; use std::sync::{Arc, Mutex}; use anyhow::{bail, format_err, Error}; @@ -12,28 +9,22 @@ use hyper::header; use hyper::{Body, StatusCode}; use url::form_urlencoded; -use http::{HeaderMap, Method}; -use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; +use openssl::ssl::SslAcceptor; use serde_json::{json, Value}; -use tokio_stream::wrappers::ReceiverStream; -use proxmox_http::client::RateLimitedStream; use proxmox_lang::try_block; use proxmox_metrics::MetricsData; -use proxmox_router::{RpcEnvironment, RpcEnvironmentType, UserInformation}; +use proxmox_router::{RpcEnvironment, RpcEnvironmentType}; use proxmox_sys::fs::{CreateOptions, FileSystemInformation}; -use proxmox_sys::linux::{ - procfs::{Loadavg, ProcFsMemInfo, ProcFsNetDev, ProcFsStat}, - socket::set_tcp_keepalive, -}; +use proxmox_sys::linux::procfs::{Loadavg, ProcFsMemInfo, ProcFsNetDev, ProcFsStat}; use proxmox_sys::logrotate::LogRotate; use proxmox_sys::{task_log, task_warn}; use pbs_datastore::DataStore; use proxmox_rest_server::{ - cleanup_old_tasks, cookie_from_header, rotate_task_log_archive, ApiConfig, AuthError, - RestEnvironment, RestServer, ServerAdapter, WorkerTask, + cleanup_old_tasks, cookie_from_header, rotate_task_log_archive, ApiConfig, RestEnvironment, + RestServer, WorkerTask, }; use proxmox_backup::rrd_cache::{ @@ -89,32 +80,6 @@ fn main() -> Result<(), Error> { proxmox_async::runtime::main(run()) } -struct ProxmoxBackupProxyAdapter; - -impl ServerAdapter for ProxmoxBackupProxyAdapter { - fn get_index( - &self, - env: RestEnvironment, - parts: Parts, - ) -> Pin> + Send>> { - Box::pin(get_index_future(env, parts)) - } - - fn check_auth<'a>( - &'a self, - headers: &'a HeaderMap, - method: &'a Method, - ) -> Pin< - Box< - dyn Future), AuthError>> - + Send - + 'a, - >, - > { - Box::pin(async move { check_pbs_auth(headers, method).await }) - } -} - /// check for a cookie with the user-preferred language, fallback to the config one if not set or /// not existing fn get_language(headers: &http::HeaderMap) -> String { @@ -217,29 +182,28 @@ async fn run() -> Result<(), Error> { let rrd_cache = initialize_rrd_cache()?; rrd_cache.apply_journal()?; - let mut config = ApiConfig::new( - pbs_buildcfg::JS_DIR, - &proxmox_backup::api2::ROUTER, - RpcEnvironmentType::PUBLIC, - ProxmoxBackupProxyAdapter, - )?; - - config.add_alias("novnc", "/usr/share/novnc-pve"); - config.add_alias("extjs", "/usr/share/javascript/extjs"); - config.add_alias("qrcodejs", "/usr/share/javascript/qrcodejs"); - config.add_alias("fontawesome", "/usr/share/fonts-font-awesome"); - config.add_alias("xtermjs", "/usr/share/pve-xtermjs"); - config.add_alias("locale", "/usr/share/pbs-i18n"); - config.add_alias( - "widgettoolkit", - "/usr/share/javascript/proxmox-widget-toolkit", - ); - config.add_alias("docs", "/usr/share/doc/proxmox-backup/html"); - let mut indexpath = PathBuf::from(pbs_buildcfg::JS_DIR); indexpath.push("index.hbs"); - config.register_template("index", &indexpath)?; - config.register_template("console", "/usr/share/pve-xtermjs/index.html.hbs")?; + + let mut config = ApiConfig::new(pbs_buildcfg::JS_DIR, RpcEnvironmentType::PUBLIC) + .index_handler_func(|e, p| Box::pin(get_index_future(e, p))) + .auth_handler_func(|h, m| Box::pin(check_pbs_auth(h, m))) + .register_template("index", &indexpath)? + .register_template("console", "/usr/share/pve-xtermjs/index.html.hbs")? + .default_api2_handler(&proxmox_backup::api2::ROUTER) + .aliases([ + ("novnc", "/usr/share/novnc-pve"), + ("extjs", "/usr/share/javascript/extjs"), + ("qrcodejs", "/usr/share/javascript/qrcodejs"), + ("fontawesome", "/usr/share/fonts-font-awesome"), + ("xtermjs", "/usr/share/pve-xtermjs"), + ("locale", "/usr/share/pbs-i18n"), + ( + "widgettoolkit", + "/usr/share/javascript/proxmox-widget-toolkit", + ), + ("docs", "/usr/share/doc/proxmox-backup/html"), + ]); let backup_user = pbs_config::backup_user()?; let mut commando_sock = proxmox_rest_server::CommandSocket::new( @@ -254,19 +218,19 @@ async fn run() -> Result<(), Error> { .owner(backup_user.uid) .group(backup_user.gid); - config.enable_access_log( - pbs_buildcfg::API_ACCESS_LOG_FN, - Some(dir_opts.clone()), - Some(file_opts.clone()), - &mut commando_sock, - )?; - - config.enable_auth_log( - pbs_buildcfg::API_AUTH_LOG_FN, - Some(dir_opts.clone()), - Some(file_opts.clone()), - &mut commando_sock, - )?; + config = config + .enable_access_log( + pbs_buildcfg::API_ACCESS_LOG_FN, + Some(dir_opts.clone()), + Some(file_opts.clone()), + &mut commando_sock, + )? + .enable_auth_log( + pbs_buildcfg::API_AUTH_LOG_FN, + Some(dir_opts.clone()), + Some(file_opts.clone()), + &mut commando_sock, + )?; let rest_server = RestServer::new(config); proxmox_rest_server::init_worker_tasks( @@ -304,11 +268,14 @@ async fn run() -> Result<(), Error> { Ok(Value::Null) })?; + let connections = proxmox_rest_server::connection::AcceptBuilder::with_acceptor(acceptor) + .debug(debug) + .rate_limiter_lookup(Arc::new(lookup_rate_limiter)) + .tcp_keepalive_time(PROXMOX_BACKUP_TCP_KEEPALIVE_TIME); let server = daemon::create_daemon( ([0, 0, 0, 0, 0, 0, 0, 0], 8007).into(), move |listener| { - let connections = accept_connections(listener, acceptor, debug); - let connections = hyper::server::accept::from_stream(ReceiverStream::new(connections)); + let connections = connections.accept(listener); Ok(async { daemon::systemd_notify(daemon::SystemdNotify::Ready)?; @@ -368,128 +335,18 @@ fn make_tls_acceptor() -> Result { let ciphers_tls_1_3 = config.ciphers_tls_1_3; let ciphers_tls_1_2 = config.ciphers_tls_1_2; - let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap(); + let mut acceptor = proxmox_rest_server::connection::TlsAcceptorBuilder::new() + .certificate_paths_pem(key_path, cert_path); + + //let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap(); if let Some(ciphers) = ciphers_tls_1_3.as_deref() { - acceptor.set_ciphersuites(ciphers)?; + acceptor = acceptor.cipher_suites(ciphers.to_string()); } if let Some(ciphers) = ciphers_tls_1_2.as_deref() { - acceptor.set_cipher_list(ciphers)?; + acceptor = acceptor.cipher_list(ciphers.to_string()); } - acceptor - .set_private_key_file(key_path, SslFiletype::PEM) - .map_err(|err| format_err!("unable to read proxy key {key_path} - {err}"))?; - acceptor - .set_certificate_chain_file(cert_path) - .map_err(|err| format_err!("unable to read proxy cert {cert_path} - {err}"))?; - acceptor.set_options(openssl::ssl::SslOptions::NO_RENEGOTIATION); - acceptor.check_private_key().unwrap(); - Ok(acceptor.build()) -} - -type ClientStreamResult = Result< - std::pin::Pin>>>, - Error, ->; -const MAX_PENDING_ACCEPTS: usize = 1024; - -fn accept_connections( - listener: tokio::net::TcpListener, - acceptor: Arc>, - debug: bool, -) -> tokio::sync::mpsc::Receiver { - let (sender, receiver) = tokio::sync::mpsc::channel(MAX_PENDING_ACCEPTS); - - tokio::spawn(accept_connection(listener, acceptor, debug, sender)); - - receiver -} - -async fn accept_connection( - listener: tokio::net::TcpListener, - acceptor: Arc>, - debug: bool, - sender: tokio::sync::mpsc::Sender, -) { - let accept_counter = Arc::new(()); - let mut shutdown_future = proxmox_rest_server::shutdown_future().fuse(); - - loop { - let (sock, peer) = select! { - res = listener.accept().fuse() => match res { - Ok(conn) => conn, - Err(err) => { - eprintln!("error accepting tcp connection: {err}"); - continue; - } - }, - _ = shutdown_future => break, - }; - - sock.set_nodelay(true).unwrap(); - let _ = set_tcp_keepalive(sock.as_raw_fd(), PROXMOX_BACKUP_TCP_KEEPALIVE_TIME); - - let sock = - RateLimitedStream::with_limiter_update_cb(sock, move || lookup_rate_limiter(peer)); - - let ssl = { - // limit acceptor_guard scope - // Acceptor can be reloaded using the command socket "reload-certificate" command - let acceptor_guard = acceptor.lock().unwrap(); - - match openssl::ssl::Ssl::new(acceptor_guard.context()) { - Ok(ssl) => ssl, - Err(err) => { - eprintln!("failed to create Ssl object from Acceptor context - {err}"); - continue; - } - } - }; - - let stream = match tokio_openssl::SslStream::new(ssl, sock) { - Ok(stream) => stream, - Err(err) => { - eprintln!("failed to create SslStream using ssl and connection socket - {err}"); - continue; - } - }; - - let mut stream = Box::pin(stream); - let sender = sender.clone(); - - if Arc::strong_count(&accept_counter) > MAX_PENDING_ACCEPTS { - eprintln!("connection rejected - to many open connections"); - continue; - } - - let accept_counter = Arc::clone(&accept_counter); - tokio::spawn(async move { - let accept_future = - tokio::time::timeout(Duration::new(10, 0), stream.as_mut().accept()); - - let result = accept_future.await; - - match result { - Ok(Ok(())) => { - if sender.send(Ok(stream)).await.is_err() && debug { - eprintln!("detect closed connection channel"); - } - } - Ok(Err(err)) => { - if debug { - eprintln!("https handshake failed - {err}"); - } - } - Err(_) => { - if debug { - eprintln!("https handshake timeout"); - } - } - } - - drop(accept_counter); // decrease reference count - }); - } + acceptor.build() } fn start_stat_generator() { diff --git a/src/bin/proxmox_backup_debug/api.rs b/src/bin/proxmox_backup_debug/api.rs index 64c22b96..3a7ef539 100644 --- a/src/bin/proxmox_backup_debug/api.rs +++ b/src/bin/proxmox_backup_debug/api.rs @@ -11,7 +11,7 @@ use proxmox_schema::{api, ApiType, ParameterSchema, Schema}; use pbs_api_types::PROXMOX_UPID_REGEX; use pbs_client::view_task_result; -use proxmox_rest_server::normalize_uri_path; +use proxmox_rest_server::normalize_path_with_components; use proxmox_backup::client_helpers::connect_to_localhost; @@ -94,7 +94,7 @@ async fn get_child_links( path: &str, rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { - let (path, components) = normalize_uri_path(path)?; + let (path, components) = normalize_path_with_components(path)?; let info = &proxmox_backup::api2::ROUTER .find_route(&components, &mut HashMap::new()) @@ -132,7 +132,7 @@ fn get_api_method( _ => unreachable!(), }; let mut uri_param = HashMap::new(); - let (path, components) = normalize_uri_path(path)?; + let (path, components) = normalize_path_with_components(path)?; if let Some(method) = &proxmox_backup::api2::ROUTER.find_method(&components, method.clone(), &mut uri_param) { @@ -384,7 +384,7 @@ async fn get_api_children( let mut res = Vec::new(); for link in get_child_links(&path, rpcenv).await? { let path = format!("{}/{}", path, link); - let (path, _) = normalize_uri_path(&path)?; + let (path, _) = normalize_path_with_components(&path)?; let mut cap = String::new(); if get_child_links(&path, rpcenv).await.is_ok() { diff --git a/src/tools/shared_rate_limiter.rs b/src/tools/shared_rate_limiter.rs index bcbeb8b9..8c9e6086 100644 --- a/src/tools/shared_rate_limiter.rs +++ b/src/tools/shared_rate_limiter.rs @@ -7,7 +7,7 @@ use nix::sys::stat::Mode; use proxmox_sys::fs::{create_path, CreateOptions}; -use proxmox_http::client::{RateLimit, RateLimiter, ShareableRateLimit}; +use proxmox_http::{RateLimit, RateLimiter, ShareableRateLimit}; use proxmox_shared_memory::{check_subtype, initialize_subtype}; use proxmox_shared_memory::{Init, SharedMemory, SharedMutex}; diff --git a/src/traffic_control_cache.rs b/src/traffic_control_cache.rs index c188069f..2e097d70 100644 --- a/src/traffic_control_cache.rs +++ b/src/traffic_control_cache.rs @@ -8,7 +8,7 @@ use std::time::Instant; use anyhow::Error; use cidr::IpInet; -use proxmox_http::client::{RateLimiter, ShareableRateLimit}; +use proxmox_http::{RateLimiter, ShareableRateLimit}; use proxmox_section_config::SectionConfigData; use proxmox_time::{parse_daily_duration, DailyDuration, TmEditor};