ferron/
main.rs

1mod acme;
2mod config;
3mod handler;
4mod listener_handler_communication;
5mod listeners;
6mod request_handler;
7mod runtime;
8mod util;
9
10use std::collections::{HashMap, HashSet};
11use std::error::Error;
12use std::net::{IpAddr, Ipv6Addr, SocketAddr};
13use std::path::{Path, PathBuf};
14use std::str::FromStr;
15use std::sync::{Arc, LazyLock, Mutex};
16use std::thread;
17use std::time::Duration;
18
19use async_channel::{Receiver, Sender};
20use base64::Engine;
21use clap::{Arg, ArgAction, ArgMatches, Command};
22use ferron_common::logging::{ErrorLogger, LogMessage};
23use ferron_common::{get_entry, get_value, get_values};
24use ferron_load_modules::{get_dns_provider, obtain_module_loaders, obtain_observability_backend_loaders};
25use human_panic::{setup_panic, Metadata};
26use instant_acme::{ChallengeType, ExternalAccountKey, LetsEncrypt};
27use mimalloc::MiMalloc;
28use rustls::client::WebPkiServerVerifier;
29use rustls::crypto::aws_lc_rs::cipher_suite::*;
30use rustls::crypto::aws_lc_rs::default_provider;
31use rustls::crypto::aws_lc_rs::kx_group::*;
32use rustls::server::{ResolvesServerCert, WebPkiClientVerifier};
33use rustls::sign::CertifiedKey;
34use rustls::version::{TLS12, TLS13};
35use rustls::{ClientConfig, RootCertStore, ServerConfig};
36use rustls_native_certs::load_native_certs;
37use rustls_platform_verifier::BuilderVerifierExt;
38use shadow_rs::shadow;
39use tokio_util::sync::CancellationToken;
40use xxhash_rust::xxh3::xxh3_128;
41
42use crate::acme::{
43  add_domain_to_cache, check_certificate_validity_or_install_cached, convert_on_demand_config, get_cached_domains,
44  provision_certificate, AcmeCache, AcmeConfig, AcmeOnDemandConfig, AcmeResolver, TlsAlpn01Resolver,
45  ACME_TLS_ALPN_NAME,
46};
47use crate::config::adapters::ConfigurationAdapter;
48use crate::config::processing::{
49  load_modules, merge_duplicates, premerge_configuration, remove_and_add_global_configuration,
50};
51use crate::config::ServerConfigurations;
52use crate::handler::create_http_handler;
53use crate::listener_handler_communication::ConnectionData;
54use crate::listeners::{create_quic_listener, create_tcp_listener};
55use crate::util::{
56  is_localhost, load_certs, load_private_key, match_hostname, CustomSniResolver, NoServerVerifier,
57  OneCertifiedKeyResolver,
58};
59
60// Set the global allocator to use mimalloc for performance optimization
61#[global_allocator]
62static GLOBAL: MiMalloc = MiMalloc;
63
64shadow!(build);
65
66static LISTENER_HANDLER_CHANNEL: LazyLock<Arc<(Sender<ConnectionData>, Receiver<ConnectionData>)>> =
67  LazyLock::new(|| Arc::new(async_channel::unbounded()));
68#[allow(clippy::type_complexity)]
69static TCP_LISTENERS: LazyLock<Arc<Mutex<HashMap<SocketAddr, CancellationToken>>>> =
70  LazyLock::new(|| Arc::new(Mutex::new(HashMap::new())));
71#[allow(clippy::type_complexity)]
72static QUIC_LISTENERS: LazyLock<Arc<Mutex<HashMap<SocketAddr, (CancellationToken, Sender<Arc<ServerConfig>>)>>>> =
73  LazyLock::new(|| Arc::new(Mutex::new(HashMap::new())));
74static URING_ENABLED: LazyLock<Arc<Mutex<Option<bool>>>> = LazyLock::new(|| Arc::new(Mutex::new(None)));
75static LISTENER_LOGGING_CHANNEL: LazyLock<Arc<(Sender<LogMessage>, Receiver<LogMessage>)>> =
76  LazyLock::new(|| Arc::new(async_channel::unbounded()));
77
78/// Handles shutdown signals (SIGHUP and CTRL+C) and returns whether to continue running
79fn handle_shutdown_signals(runtime: &tokio::runtime::Runtime) -> bool {
80  runtime.block_on(async move {
81    let (continue_tx, continue_rx) = async_channel::unbounded::<bool>();
82    let cancel_token = tokio_util::sync::CancellationToken::new();
83
84    #[cfg(unix)]
85    {
86      let cancel_token_clone = cancel_token.clone();
87      let continue_tx_clone = continue_tx.clone();
88      tokio::spawn(async move {
89        if let Ok(mut signal) = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::hangup()) {
90          tokio::select! {
91            _ = signal.recv() => {
92              continue_tx_clone.send(true).await.unwrap_or_default();
93            }
94            _ = cancel_token_clone.cancelled() => {}
95          }
96        }
97      });
98    }
99
100    let cancel_token_clone = cancel_token.clone();
101    tokio::spawn(async move {
102      tokio::select! {
103        result = tokio::signal::ctrl_c() => {
104          if result.is_ok() {
105            continue_tx.send(false).await.unwrap_or_default();
106          }
107        }
108        _ = cancel_token_clone.cancelled() => {}
109      }
110    });
111
112    let continue_running = continue_rx.recv().await.unwrap_or(false);
113    cancel_token.cancel();
114    continue_running
115  })
116}
117
118/// Function called before starting a server
119fn before_starting_server(
120  args: ArgMatches,
121  configuration_adapters: HashMap<String, Box<dyn ConfigurationAdapter + Send + Sync>>,
122) -> Result<(), Box<dyn Error + Send + Sync>> {
123  // Obtain the argument values
124  let configuration_path: &Path = args
125    .get_one::<PathBuf>("config")
126    .ok_or(anyhow::anyhow!("Cannot obtain the configuration path"))?
127    .as_path();
128  let configuration_adapter: &str = args
129    .get_one::<String>("config-adapter")
130    .map_or(determine_default_configuration_adapter(configuration_path), |s| {
131      s as &str
132    });
133
134  // Old handler shutdown channels and secondary runtime
135  let mut old_runtime: Option<(Vec<CancellationToken>, tokio::runtime::Runtime)> = None;
136
137  // Obtain the configuration adapter
138  let configuration_adapter = configuration_adapters
139    .get(configuration_adapter)
140    .ok_or(anyhow::anyhow!(
141      "The \"{}\" configuration adapter isn't supported",
142      configuration_adapter
143    ))?;
144
145  // Determine the available parallelism
146  let available_parallelism = thread::available_parallelism()?.get();
147
148  // First startup flag
149  let mut first_startup = true;
150
151  loop {
152    // Obtain the module loaders
153    let mut module_loaders = obtain_module_loaders();
154
155    // Obtain the observability backend loaders
156    let mut observability_backend_loaders = obtain_observability_backend_loaders();
157
158    // Create a secondary Tokio runtime
159    let secondary_runtime = tokio::runtime::Builder::new_multi_thread()
160      .worker_threads(match available_parallelism / 2 {
161        0 => 1,
162        non_zero => non_zero,
163      })
164      .thread_name("Secondary runtime")
165      .enable_all()
166      .build()?;
167
168    // Load the configuration
169    let configs_to_process = configuration_adapter.load_configuration(configuration_path)?;
170
171    // Process the configurations
172    let configs_to_process = merge_duplicates(configs_to_process);
173    let configs_to_process = remove_and_add_global_configuration(configs_to_process);
174    let configs_to_process = premerge_configuration(configs_to_process);
175    let (configs_to_process, first_module_error, unused_properties) = load_modules(
176      configs_to_process,
177      &mut module_loaders,
178      &mut observability_backend_loaders,
179      &secondary_runtime,
180    );
181
182    // Finalize the configurations
183    let server_configurations = Arc::new(ServerConfigurations::new(configs_to_process));
184
185    let global_configuration = server_configurations.find_global_configuration();
186    let global_configuration_clone = global_configuration.clone();
187
188    // Reference to the secondary Tokio runtime
189    let secondary_runtime_ref = &secondary_runtime;
190
191    // Mutable reference to the old runtime
192    let old_runtime_ref = &mut old_runtime;
193
194    // Execute the rest
195    let execute_rest = move || {
196      if let Some(first_module_error) = first_module_error {
197        // Error out if there was a module error
198        Err(first_module_error)?;
199      }
200
201      // Log unused properties
202      for unused_property in unused_properties {
203        for logging_tx in global_configuration
204          .as_ref()
205          .map_or(&vec![], |c| &c.observability.log_channels)
206        {
207          logging_tx
208            .send_blocking(LogMessage::new(
209              format!("Unused configuration property detected: \"{unused_property}\""),
210              true,
211            ))
212            .unwrap_or_default();
213        }
214      }
215
216      // Configure cryptography provider for Rustls
217      let mut crypto_provider = default_provider();
218
219      // Configure cipher suites
220      let cipher_suite: Vec<&config::ServerConfigurationValue> = global_configuration
221        .as_deref()
222        .map_or(vec![], |c| get_values!("tls_cipher_suite", c));
223      if !cipher_suite.is_empty() {
224        let mut cipher_suites = Vec::new();
225        let cipher_suite_iter = cipher_suite.iter();
226        for cipher_suite_config in cipher_suite_iter {
227          if let Some(cipher_suite) = cipher_suite_config.as_str() {
228            let cipher_suite_to_add = match cipher_suite {
229              "TLS_AES_128_GCM_SHA256" => TLS13_AES_128_GCM_SHA256,
230              "TLS_AES_256_GCM_SHA384" => TLS13_AES_256_GCM_SHA384,
231              "TLS_CHACHA20_POLY1305_SHA256" => TLS13_CHACHA20_POLY1305_SHA256,
232              "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
233              "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
234              "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
235              "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
236              "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" => TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
237              "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
238              _ => Err(anyhow::anyhow!(
239                "The \"{}\" cipher suite is not supported",
240                cipher_suite
241              ))?,
242            };
243            cipher_suites.push(cipher_suite_to_add);
244          }
245        }
246        crypto_provider.cipher_suites = cipher_suites;
247      }
248
249      // Configure ECDH curves
250      let ecdh_curves = global_configuration
251        .as_deref()
252        .map_or(vec![], |c| get_values!("tls_ecdh_curve", c));
253      if !ecdh_curves.is_empty() {
254        let mut kx_groups = Vec::new();
255        let ecdh_curves_iter = ecdh_curves.iter();
256        for ecdh_curve_config in ecdh_curves_iter {
257          if let Some(ecdh_curve) = ecdh_curve_config.as_str() {
258            let kx_group_to_add = match ecdh_curve {
259              "secp256r1" => SECP256R1,
260              "secp384r1" => SECP384R1,
261              "x25519" => X25519,
262              "x25519mklem768" => X25519MLKEM768,
263              "mklem768" => MLKEM768,
264              _ => Err(anyhow::anyhow!("The \"{}\" ECDH curve is not supported", ecdh_curve))?,
265            };
266            kx_groups.push(kx_group_to_add);
267          }
268        }
269        crypto_provider.kx_groups = kx_groups;
270      }
271
272      // Install a process-wide cryptography provider. If it fails, then error it out.
273      if crypto_provider.clone().install_default().is_err() && first_startup {
274        Err(anyhow::anyhow!("Cannot install a process-wide cryptography provider"))?;
275      }
276
277      let crypto_provider = Arc::new(crypto_provider);
278
279      // Build TLS configuration
280      let tls_config_builder_wants_versions = ServerConfig::builder_with_provider(crypto_provider.clone());
281
282      let min_tls_version_option = global_configuration
283        .as_deref()
284        .and_then(|c| get_value!("tls_min_version", c))
285        .and_then(|v| v.as_str());
286      let max_tls_version_option = global_configuration
287        .as_deref()
288        .and_then(|c| get_value!("tls_max_version", c))
289        .and_then(|v| v.as_str());
290
291      let tls_config_builder_wants_verifier = if min_tls_version_option.is_none() && max_tls_version_option.is_none() {
292        tls_config_builder_wants_versions.with_safe_default_protocol_versions()?
293      } else {
294        let tls_versions = [("TLSv1.2", &TLS12), ("TLSv1.3", &TLS13)];
295        let min_tls_version_index = min_tls_version_option
296          .map_or(Some(0), |v| tls_versions.iter().position(|p| p.0 == v))
297          .ok_or(anyhow::anyhow!("Invalid minimum TLS version"))?;
298        let max_tls_version_index = max_tls_version_option
299          .map_or(Some(tls_versions.len() - 1), |v| {
300            tls_versions.iter().position(|p| p.0 == v)
301          })
302          .ok_or(anyhow::anyhow!("Invalid maximum TLS version"))?;
303        if max_tls_version_index < min_tls_version_index {
304          Err(anyhow::anyhow!("Maximum TLS version is older than minimum TLS version"))?
305        }
306        tls_config_builder_wants_versions.with_protocol_versions(
307          &tls_versions[min_tls_version_index..=max_tls_version_index]
308            .iter()
309            .map(|p| p.1)
310            .collect::<Vec<_>>(),
311        )?
312      };
313
314      let tls_config_builder_wants_server_cert = if let Some(client_cert_path) = global_configuration
315        .as_deref()
316        .and_then(|c| get_value!("tls_client_certificate", c))
317        .and_then(|v| v.as_str())
318      {
319        let mut roots = RootCertStore::empty();
320        let client_certificate_cas = load_certs(client_cert_path)?;
321        for cert in client_certificate_cas {
322          roots.add(cert)?;
323        }
324        tls_config_builder_wants_verifier
325          .with_client_cert_verifier(WebPkiClientVerifier::builder(Arc::new(roots)).build()?)
326      } else if global_configuration
327        .as_deref()
328        .and_then(|c| get_value!("tls_client_certificate", c))
329        .and_then(|v| v.as_bool())
330        .unwrap_or(false)
331      {
332        let roots = (|| {
333          let certs_result = load_native_certs();
334          if !certs_result.errors.is_empty() {
335            return None;
336          }
337          let certs = certs_result.certs;
338
339          let mut roots = RootCertStore::empty();
340          for cert in certs {
341            if roots.add(cert).is_err() {
342              return None;
343            }
344          }
345
346          Some(roots)
347        })()
348        .unwrap_or(RootCertStore {
349          roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
350        });
351
352        tls_config_builder_wants_verifier
353          .with_client_cert_verifier(WebPkiClientVerifier::builder(Arc::new(roots)).build()?)
354      } else {
355        tls_config_builder_wants_verifier.with_no_client_auth()
356      };
357
358      let enable_proxy_protocol = global_configuration
359        .as_ref()
360        .and_then(|c| get_value!("protocol_proxy", c))
361        .and_then(|v| v.as_bool())
362        .unwrap_or(false);
363      let protocols = global_configuration
364        .as_ref()
365        .and_then(|c| get_entry!("protocols", c))
366        .map(|e| e.values.iter().filter_map(|v| v.as_str()).collect::<Vec<_>>())
367        .unwrap_or(vec!["h1", "h2"]);
368
369      if enable_proxy_protocol && protocols.contains(&"h3") {
370        Err(anyhow::anyhow!("PROXY protocol isn't supported with HTTP/3"))?
371      }
372
373      let default_http_port = global_configuration
374        .as_deref()
375        .and_then(|c| get_entry!("default_http_port", c))
376        .and_then(|e| e.values.first())
377        .map_or(Some(80), |v| {
378          if v.is_null() {
379            None
380          } else {
381            Some(v.as_i128().unwrap_or(80) as u16)
382          }
383        });
384      let default_https_port = global_configuration
385        .as_deref()
386        .and_then(|c| get_entry!("default_https_port", c))
387        .and_then(|e| e.values.first())
388        .map_or(Some(443), |v| {
389          if v.is_null() {
390            None
391          } else {
392            Some(v.as_i128().unwrap_or(443) as u16)
393          }
394        });
395
396      let mut tls_ports: HashMap<u16, CustomSniResolver> = HashMap::new();
397      #[allow(clippy::type_complexity)]
398      let mut tls_port_locks: HashMap<u16, Arc<tokio::sync::RwLock<Vec<(String, Arc<dyn ResolvesServerCert>)>>>> =
399        HashMap::new();
400      let mut nonencrypted_ports = HashSet::new();
401      let mut certified_keys_to_preload: HashMap<u16, Vec<Arc<CertifiedKey>>> = HashMap::new();
402      let mut used_sni_hostnames = HashSet::new();
403      let mut automatic_tls_used_sni_hostnames = HashSet::new();
404      let mut acme_tls_alpn_01_resolvers: HashMap<u16, TlsAlpn01Resolver> = HashMap::new();
405      let mut acme_tls_alpn_01_resolver_locks: HashMap<
406        u16,
407        Arc<tokio::sync::RwLock<Vec<crate::acme::TlsAlpn01DataLock>>>,
408      > = HashMap::new();
409      let acme_http_01_resolvers: Arc<tokio::sync::RwLock<Vec<crate::acme::Http01DataLock>>> =
410        Arc::new(tokio::sync::RwLock::new(Vec::new()));
411      let acme_default_directory = dirs::data_local_dir().and_then(|mut p| {
412        p.push("ferron-acme");
413        p.into_os_string().into_string().ok()
414      });
415      let memory_acme_account_cache_data = Arc::new(tokio::sync::RwLock::new(HashMap::new()));
416      let mut acme_configs = Vec::new();
417      let mut acme_on_demand_configs = Vec::new();
418      let (acme_on_demand_tx, acme_on_demand_rx) = async_channel::unbounded();
419      let on_demand_tls_ask_endpoint = match global_configuration
420        .as_ref()
421        .and_then(|c| get_value!("auto_tls_on_demand_ask", c))
422        .and_then(|v| v.as_str())
423        .map(|u| u.parse::<hyper::Uri>())
424      {
425        Some(Ok(uri)) => Some(uri),
426        Some(Err(err)) => Err(anyhow::anyhow!(
427          "Failed to parse automatic TLS on demand asking endpoint URI: {}",
428          err
429        ))?,
430        None => None,
431      };
432      let on_demand_tls_ask_endpoint_verify = !global_configuration
433        .as_ref()
434        .and_then(|c| get_value!("auto_tls_on_demand_ask_no_verification", c))
435        .and_then(|v| v.as_bool())
436        .unwrap_or(false);
437
438      // Iterate server configurations (TLS configuration)
439      for server_configuration in &server_configurations.inner {
440        if server_configuration.filters.is_global_non_host()
441          || (server_configuration.filters.is_global() && server_configuration.entries.is_empty())
442        {
443          // Don't add listeners from an empty global configuration or non-host global configuration
444          continue;
445        }
446
447        let on_demand_tls = get_value!("auto_tls_on_demand", server_configuration)
448          .and_then(|v| v.as_bool())
449          .unwrap_or(false);
450
451        let https_port = server_configuration.filters.port.or(default_https_port);
452
453        let sni_hostname = server_configuration.filters.hostname.clone().or_else(|| {
454          // !!! UNTESTED, many clients don't send SNI hostname when accessing via IP address anyway
455          match server_configuration.filters.ip {
456            Some(IpAddr::V4(address)) => Some(address.to_string()),
457            Some(IpAddr::V6(address)) => Some(format!("[{address}]")),
458            _ => None,
459          }
460        });
461
462        let is_sni_hostname_used = !https_port.is_none_or(|p| {
463          !used_sni_hostnames.contains(&(p, sni_hostname.clone()))
464            && !automatic_tls_used_sni_hostnames.contains(&(p, sni_hostname.clone()))
465        });
466        let is_auto_tls_sni_hostname_used =
467          https_port.is_some_and(|p| automatic_tls_used_sni_hostnames.contains(&(p, sni_hostname.clone())));
468
469        let mut automatic_tls_port = None;
470        if server_configuration.filters.port.is_none() {
471          if get_value!("auto_tls", server_configuration)
472            .and_then(|v| v.as_bool())
473            .unwrap_or(!is_localhost(
474              server_configuration.filters.ip.as_ref(),
475              server_configuration.filters.hostname.as_deref(),
476            ))
477          {
478            automatic_tls_port = default_https_port;
479          }
480          if let Some(http_port) = default_http_port {
481            nonencrypted_ports.insert(http_port);
482          }
483        }
484
485        if get_value!("auto_tls", server_configuration)
486          .and_then(|v| v.as_bool())
487          .unwrap_or(false)
488        {
489          automatic_tls_port = https_port;
490        } else if let Some(tls_entry) = get_entry!("tls", server_configuration) {
491          if let Some(https_port) = https_port {
492            if tls_entry.values.len() == 2 {
493              if let Some(cert_path) = tls_entry.values[0].as_str() {
494                if let Some(key_path) = tls_entry.values[1].as_str() {
495                  automatic_tls_port = None;
496
497                  if !is_sni_hostname_used {
498                    let certs = match load_certs(cert_path) {
499                      Ok(certs) => certs,
500                      Err(err) => Err(anyhow::anyhow!(
501                        "Cannot load the \"{}\" TLS certificate: {}",
502                        cert_path,
503                        err
504                      ))?,
505                    };
506                    let key = match load_private_key(key_path) {
507                      Ok(key) => key,
508                      Err(err) => Err(anyhow::anyhow!("Cannot load the \"{}\" private key: {}", key_path, err))?,
509                    };
510                    let signing_key = match crypto_provider.key_provider.load_private_key(key) {
511                      Ok(key) => key,
512                      Err(err) => Err(anyhow::anyhow!("Cannot load the \"{}\" private key: {}", key_path, err))?,
513                    };
514                    let certified_key = Arc::new(CertifiedKey::new(certs, signing_key));
515                    if let Some(certified_keys) = certified_keys_to_preload.get_mut(&https_port) {
516                      certified_keys.push(certified_key.clone());
517                    } else {
518                      certified_keys_to_preload.insert(https_port, vec![certified_key.clone()]);
519                    }
520                    let resolver = Arc::new(OneCertifiedKeyResolver::new(certified_key));
521                    if let Some(sni_resolver) = tls_ports.get_mut(&https_port) {
522                      if let Some(sni_hostname) = &sni_hostname {
523                        sni_resolver.load_host_resolver(sni_hostname, resolver);
524                      } else {
525                        sni_resolver.load_fallback_resolver(resolver);
526                      }
527                    } else {
528                      let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
529                      tls_port_locks.insert(https_port, sni_resolver_list.clone());
530                      let mut sni_resolver = CustomSniResolver::with_resolvers(sni_resolver_list);
531                      if let Some(sni_hostname) = &sni_hostname {
532                        sni_resolver.load_host_resolver(sni_hostname, resolver);
533                      } else {
534                        sni_resolver.load_fallback_resolver(resolver);
535                      }
536                      tls_ports.insert(https_port, sni_resolver);
537                    }
538                    used_sni_hostnames.insert((https_port, sni_hostname.clone()));
539                  }
540                }
541              }
542            }
543          }
544        } else if let Some(http_port) = server_configuration.filters.port.or(default_http_port) {
545          nonencrypted_ports.insert(http_port);
546        }
547        if let Some(automatic_tls_port) = automatic_tls_port {
548          if !is_auto_tls_sni_hostname_used {
549            if sni_hostname.is_some() || on_demand_tls {
550              let is_wildcard_domain = sni_hostname.as_ref().is_some_and(|s| s.starts_with("*."));
551              let challenge_type_entry = get_entry!("auto_tls_challenge", server_configuration);
552              let challenge_type_str = challenge_type_entry
553                .and_then(|e| e.values.first())
554                .and_then(|v| v.as_str())
555                .unwrap_or("tls-alpn-01");
556              let challenge_params = challenge_type_entry
557                .and_then(|e| {
558                  let mut props_str = HashMap::new();
559                  for (prop_name, prop_value) in e.props.iter() {
560                    if let Some(prop_value) = prop_value.as_str() {
561                      props_str.insert(prop_name.to_string(), prop_value.to_string());
562                    }
563                  }
564                  if props_str.is_empty() {
565                    None
566                  } else {
567                    Some(props_str)
568                  }
569                })
570                .unwrap_or(HashMap::new());
571              if let Some(sni_hostname) = &sni_hostname {
572                if sni_hostname.parse::<IpAddr>().is_ok() {
573                  for logging_tx in global_configuration
574                    .as_ref()
575                    .map_or(&vec![], |c| &c.observability.log_channels)
576                  {
577                    logging_tx
578                    .send_blocking(LogMessage::new(
579                      format!("Ferron's automatic TLS functionality doesn't support IP address-based identifiers, skipping SNI host \"{sni_hostname}\"..."),
580                      true,
581                    ))
582                    .unwrap_or_default();
583                  }
584                  continue;
585                }
586              }
587              let challenge_type = match &*challenge_type_str.to_uppercase() {
588                "HTTP-01" => {
589                  if let Some(sni_hostname) = &sni_hostname {
590                    if is_wildcard_domain && !on_demand_tls {
591                      for logging_tx in global_configuration
592                        .as_ref()
593                        .map_or(&vec![], |c| &c.observability.log_channels)
594                      {
595                        logging_tx
596                        .send_blocking(LogMessage::new(
597                          format!("HTTP-01 ACME challenge doesn't support wildcard hostnames, skipping SNI host \"{sni_hostname}\"..."),
598                          true,
599                        ))
600                        .unwrap_or_default();
601                      }
602                      continue;
603                    }
604                  }
605                  ChallengeType::Http01
606                }
607                "TLS-ALPN-01" => {
608                  if let Some(sni_hostname) = &sni_hostname {
609                    if is_wildcard_domain && !on_demand_tls {
610                      for logging_tx in global_configuration
611                        .as_ref()
612                        .map_or(&vec![], |c| &c.observability.log_channels)
613                      {
614                        logging_tx
615                        .send_blocking(LogMessage::new(
616                          format!("TLS-ALPN-01 ACME challenge doesn't support wildcard hostnames, skipping SNI host \"{sni_hostname}\"..."),
617                          true,
618                        ))
619                        .unwrap_or_default();
620                      }
621                      continue;
622                    }
623                  }
624                  ChallengeType::TlsAlpn01
625                }
626                "DNS-01" => ChallengeType::Dns01,
627                unsupported => Err(anyhow::anyhow!("Unsupported ACME challenge type: {}", unsupported))?,
628              };
629              let dns_provider: Option<Arc<dyn ferron_common::dns::DnsProvider + Send + Sync>> =
630                if &*challenge_type_str.to_uppercase() != "DNS-01" {
631                  None
632                } else {
633                  let provider_name = challenge_params
634                    .get("provider")
635                    .ok_or(anyhow::anyhow!("No DNS provider specified"))?;
636                  Some(get_dns_provider(provider_name, &challenge_params)?)
637                };
638              let acme_cache_path_option = get_value!("auto_tls_cache", server_configuration)
639                .map_or(acme_default_directory.as_deref(), |v| {
640                  if v.is_null() {
641                    None
642                  } else if let Some(v) = v.as_str() {
643                    Some(v)
644                  } else {
645                    acme_default_directory.as_deref()
646                  }
647                })
648                .map(|path| path.to_owned());
649              let rustls_client_config = (if get_value!("auto_tls_no_verification", server_configuration)
650                .and_then(|v| v.as_bool())
651                .unwrap_or(false)
652              {
653                ClientConfig::builder_with_provider(crypto_provider.clone())
654                  .with_safe_default_protocol_versions()?
655                  .dangerous()
656                  .with_custom_certificate_verifier(Arc::new(NoServerVerifier::new()))
657              } else if let Ok(client_config) = BuilderVerifierExt::with_platform_verifier(
658                ClientConfig::builder_with_provider(crypto_provider.clone()).with_safe_default_protocol_versions()?,
659              ) {
660                client_config
661              } else {
662                ClientConfig::builder_with_provider(crypto_provider.clone())
663                  .with_safe_default_protocol_versions()?
664                  .with_webpki_verifier(
665                    WebPkiServerVerifier::builder(Arc::new(rustls::RootCertStore {
666                      roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
667                    }))
668                    .build()?,
669                  )
670              })
671              .with_no_client_auth();
672              if on_demand_tls {
673                if &*challenge_type_str.to_uppercase() == "TLS-ALPN-01" {
674                  // Add TLS-ALPN-01 resolver
675                  let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
676                  acme_tls_alpn_01_resolver_locks.insert(automatic_tls_port, sni_resolver_list.clone());
677                  let sni_resolver = TlsAlpn01Resolver::with_resolvers(sni_resolver_list);
678                  acme_tls_alpn_01_resolvers.insert(automatic_tls_port, sni_resolver);
679                }
680
681                if let Some(sni_resolver) = tls_ports.get_mut(&automatic_tls_port) {
682                  sni_resolver.load_fallback_sender(acme_on_demand_tx.clone(), automatic_tls_port);
683                } else {
684                  let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
685                  tls_port_locks.insert(automatic_tls_port, sni_resolver_list.clone());
686                  let mut sni_resolver = CustomSniResolver::with_resolvers(sni_resolver_list);
687                  sni_resolver.load_fallback_sender(acme_on_demand_tx.clone(), automatic_tls_port);
688                  tls_ports.insert(automatic_tls_port, sni_resolver);
689                }
690
691                let acme_on_demand_config = AcmeOnDemandConfig {
692                  rustls_client_config,
693                  challenge_type,
694                  contact: if let Some(contact) =
695                    get_value!("auto_tls_contact", server_configuration).and_then(|v| v.as_str())
696                  {
697                    vec![format!("mailto:{}", contact.to_string())]
698                  } else {
699                    vec![]
700                  },
701                  directory: if let Some(directory) =
702                    get_value!("auto_tls_directory", server_configuration).and_then(|v| v.as_str())
703                  {
704                    directory.to_string()
705                  } else if get_value!("auto_tls_letsencrypt_production", server_configuration)
706                    .and_then(|v| v.as_bool())
707                    .unwrap_or(true)
708                  {
709                    LetsEncrypt::Production.url().to_string()
710                  } else {
711                    LetsEncrypt::Staging.url().to_string()
712                  },
713                  eab_key: if let Some(eab_key_entry) = get_entry!("auto_tls_eab", server_configuration) {
714                    if let Some(eab_key_id) = eab_key_entry.values.first().and_then(|v| v.as_str()) {
715                      if let Some(eab_key_hmac) = eab_key_entry.values.get(1).and_then(|v| v.as_str()) {
716                        match base64::engine::general_purpose::URL_SAFE_NO_PAD
717                          .decode(eab_key_hmac.trim_end_matches('='))
718                        {
719                          Ok(decoded_key) => {
720                            Some(Arc::new(ExternalAccountKey::new(eab_key_id.to_string(), &decoded_key)))
721                          }
722                          Err(err) => Err(anyhow::anyhow!("Failed to decode EAB key HMAC: {}", err))?,
723                        }
724                      } else {
725                        None
726                      }
727                    } else {
728                      None
729                    }
730                  } else {
731                    None
732                  },
733                  profile: get_value!("auto_tls_profile", server_configuration)
734                    .and_then(|v| v.as_str().map(|s| s.to_string())),
735                  cache_path: if let Some(acme_cache_path) = acme_cache_path_option.as_ref() {
736                    Some(PathBuf::from_str(acme_cache_path).map_err(|_| anyhow::anyhow!("Invalid ACME cache path"))?)
737                  } else {
738                    None
739                  },
740                  sni_resolver_lock: tls_port_locks
741                    .get(&automatic_tls_port)
742                    .cloned()
743                    .unwrap_or(Arc::new(tokio::sync::RwLock::new(Vec::new()))),
744                  tls_alpn_01_resolver_lock: acme_tls_alpn_01_resolver_locks
745                    .get(&automatic_tls_port)
746                    .cloned()
747                    .unwrap_or(Arc::new(tokio::sync::RwLock::new(Vec::new()))),
748                  http_01_resolver_lock: acme_http_01_resolvers.clone(),
749                  dns_provider,
750                  sni_hostname: sni_hostname.clone(),
751                  port: automatic_tls_port,
752                };
753                acme_on_demand_configs.push(acme_on_demand_config);
754                automatic_tls_used_sni_hostnames.insert((automatic_tls_port, sni_hostname));
755              } else if let Some(sni_hostname) = sni_hostname {
756                let (account_cache_path, cert_cache_path) =
757                  if let Some(acme_cache_path) = acme_cache_path_option.as_deref() {
758                    let mut pathbuf =
759                      PathBuf::from_str(acme_cache_path).map_err(|_| anyhow::anyhow!("Invalid ACME cache path"))?;
760                    let base_pathbuf = pathbuf.clone();
761                    let append_hash = base64::engine::general_purpose::URL_SAFE_NO_PAD
762                      .encode(xxh3_128(format!("{automatic_tls_port}-{sni_hostname}").as_bytes()).to_be_bytes());
763                    pathbuf.push(append_hash);
764                    (Some(base_pathbuf), Some(pathbuf))
765                  } else {
766                    (None, None)
767                  };
768                let certified_key_lock = Arc::new(tokio::sync::RwLock::new(None));
769                let tls_alpn_01_data_lock = Arc::new(tokio::sync::RwLock::new(None));
770                let http_01_data_lock = Arc::new(tokio::sync::RwLock::new(None));
771                let acme_config = AcmeConfig {
772                  rustls_client_config,
773                  domains: vec![sni_hostname.clone()],
774                  challenge_type,
775                  contact: if let Some(contact) =
776                    get_value!("auto_tls_contact", server_configuration).and_then(|v| v.as_str())
777                  {
778                    vec![format!("mailto:{}", contact.to_string())]
779                  } else {
780                    vec![]
781                  },
782                  directory: if let Some(directory) =
783                    get_value!("auto_tls_directory", server_configuration).and_then(|v| v.as_str())
784                  {
785                    directory.to_string()
786                  } else if get_value!("auto_tls_letsencrypt_production", server_configuration)
787                    .and_then(|v| v.as_bool())
788                    .unwrap_or(true)
789                  {
790                    LetsEncrypt::Production.url().to_string()
791                  } else {
792                    LetsEncrypt::Staging.url().to_string()
793                  },
794                  eab_key: if let Some(eab_key_entry) = get_entry!("auto_tls_eab", server_configuration) {
795                    if let Some(eab_key_id) = eab_key_entry.values.first().and_then(|v| v.as_str()) {
796                      if let Some(eab_key_hmac) = eab_key_entry.values.get(1).and_then(|v| v.as_str()) {
797                        Some(Arc::new(ExternalAccountKey::new(
798                          eab_key_id.to_string(),
799                          &base64::engine::general_purpose::URL_SAFE_NO_PAD
800                            .decode(eab_key_hmac.trim_end_matches('='))
801                            .map_err(|err| anyhow::anyhow!("Failed to decode EAB key HMAC: {}", err))?,
802                        )))
803                      } else {
804                        None
805                      }
806                    } else {
807                      None
808                    }
809                  } else {
810                    None
811                  },
812                  profile: get_value!("auto_tls_profile", server_configuration)
813                    .and_then(|v| v.as_str().map(|s| s.to_string())),
814                  account_cache: if let Some(account_cache_path) = account_cache_path {
815                    AcmeCache::File(account_cache_path)
816                  } else {
817                    AcmeCache::Memory(memory_acme_account_cache_data.clone())
818                  },
819                  certificate_cache: if let Some(cert_cache_path) = cert_cache_path {
820                    AcmeCache::File(cert_cache_path)
821                  } else {
822                    AcmeCache::Memory(Arc::new(tokio::sync::RwLock::new(HashMap::new())))
823                  },
824                  certified_key_lock: certified_key_lock.clone(),
825                  tls_alpn_01_data_lock: tls_alpn_01_data_lock.clone(),
826                  http_01_data_lock: http_01_data_lock.clone(),
827                  dns_provider,
828                  renewal_info: None,
829                  account: None,
830                };
831                let acme_resolver = Arc::new(AcmeResolver::new(certified_key_lock));
832                acme_configs.push(acme_config);
833                match &*challenge_type_str.to_uppercase() {
834                  "HTTP-01" => {
835                    acme_http_01_resolvers.blocking_write().push(http_01_data_lock);
836                  }
837                  "TLS-ALPN-01" => {
838                    if let Some(sni_resolver) = acme_tls_alpn_01_resolvers.get_mut(&automatic_tls_port) {
839                      sni_resolver.load_resolver(tls_alpn_01_data_lock);
840                    } else {
841                      let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
842                      acme_tls_alpn_01_resolver_locks.insert(automatic_tls_port, sni_resolver_list.clone());
843                      let sni_resolver = TlsAlpn01Resolver::with_resolvers(sni_resolver_list);
844                      sni_resolver.load_resolver(tls_alpn_01_data_lock);
845                      acme_tls_alpn_01_resolvers.insert(automatic_tls_port, sni_resolver);
846                    }
847                  }
848                  _ => (),
849                }
850                if let Some(sni_resolver) = tls_ports.get_mut(&automatic_tls_port) {
851                  sni_resolver.load_host_resolver(&sni_hostname, acme_resolver);
852                } else {
853                  let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
854                  tls_port_locks.insert(automatic_tls_port, sni_resolver_list.clone());
855                  let mut sni_resolver = CustomSniResolver::with_resolvers(sni_resolver_list);
856                  sni_resolver.load_host_resolver(&sni_hostname, acme_resolver);
857                  tls_ports.insert(automatic_tls_port, sni_resolver);
858                }
859                automatic_tls_used_sni_hostnames.insert((automatic_tls_port, Some(sni_hostname)));
860              }
861            } else if !server_configuration.filters.is_global() && !server_configuration.filters.is_global_non_host() {
862              for logging_tx in global_configuration
863                .as_ref()
864                .map_or(&vec![], |c| &c.observability.log_channels)
865              {
866                logging_tx
867                  .send_blocking(LogMessage::new(
868                    "Skipping automatic TLS for a host without a SNI hostname...".to_string(),
869                    true,
870                  ))
871                  .unwrap_or_default();
872              }
873            }
874          }
875        }
876      }
877
878      // Shut down request handler threads and secondary runtime
879      if let Some((handler_shutdown_channels, secondary_runtime)) = old_runtime_ref.take() {
880        for shutdown in handler_shutdown_channels {
881          shutdown.cancel();
882        }
883        drop(secondary_runtime);
884      }
885
886      if !acme_configs.is_empty() || !acme_on_demand_configs.is_empty() {
887        // Spawn a task to handle ACME certificate provisioning, one certificate at time
888
889        let global_configuration_clone = global_configuration.clone();
890        secondary_runtime_ref.spawn(async move {
891          for acme_config in &mut acme_configs {
892            // Install the certificates from the cache if they're valid
893            check_certificate_validity_or_install_cached(acme_config, None)
894              .await
895              .unwrap_or_default();
896          }
897
898          let mut existing_combinations = HashSet::new();
899          for acme_on_demand_config in &mut acme_on_demand_configs {
900            for cached_domain in get_cached_domains(acme_on_demand_config).await {
901              let mut acme_config = convert_on_demand_config(
902                acme_on_demand_config,
903                cached_domain.clone(),
904                memory_acme_account_cache_data.clone(),
905              )
906              .await;
907
908              existing_combinations.insert((cached_domain, acme_on_demand_config.port));
909
910              // Install the certificates from the cache if they're valid
911              check_certificate_validity_or_install_cached(&mut acme_config, None)
912                .await
913                .unwrap_or_default();
914
915              acme_configs.push(acme_config);
916            }
917          }
918
919          // Wrap ACME configurations in a mutex
920          let acme_configs_mutex = Arc::new(tokio::sync::Mutex::new(acme_configs));
921
922          let prevent_file_race_conditions_mutex = Arc::new(tokio::sync::Mutex::new(()));
923
924          if !acme_on_demand_configs.is_empty() {
925            // On-demand TLS
926            let acme_configs_mutex = acme_configs_mutex.clone();
927            let acme_on_demand_configs = Arc::new(acme_on_demand_configs);
928            let global_configuration_clone = global_configuration_clone.clone();
929            tokio::spawn(async move {
930              let mut existing_combinations = existing_combinations;
931              while let Ok(received_data) = acme_on_demand_rx.recv().await {
932                let on_demand_tls_ask_endpoint = on_demand_tls_ask_endpoint.clone();
933                if let Some(on_demand_tls_ask_endpoint) = on_demand_tls_ask_endpoint {
934                  let mut url_parts = on_demand_tls_ask_endpoint.into_parts();
935                  if let Some(path_and_query) = url_parts.path_and_query {
936                    let query = path_and_query.query();
937                    let query = if let Some(query) = query {
938                      format!("{}&domain={}", query, urlencoding::encode(&received_data.0))
939                    } else {
940                      format!("domain={}", urlencoding::encode(&received_data.0))
941                    };
942                    url_parts.path_and_query = Some(match format!("{}?{}", path_and_query.path(), query).parse() {
943                      Ok(parsed) => parsed,
944                      Err(err) => {
945                        for acme_logger in global_configuration_clone
946                          .as_ref()
947                          .map_or(&vec![], |c| &c.observability.log_channels)
948                        {
949                          acme_logger
950                            .send(LogMessage::new(
951                              format!("Error while formatting the URL for on-demand TLS request: {err}"),
952                              true,
953                            ))
954                            .await
955                            .unwrap_or_default();
956                        }
957                        continue;
958                      }
959                    });
960                  } else {
961                    url_parts.path_and_query = Some(
962                      match format!("/?domain={}", urlencoding::encode(&received_data.0)).parse() {
963                        Ok(parsed) => parsed,
964                        Err(err) => {
965                          for acme_logger in global_configuration_clone
966                            .as_ref()
967                            .map_or(&vec![], |c| &c.observability.log_channels)
968                          {
969                            acme_logger
970                              .send(LogMessage::new(
971                                format!("Error while formatting the URL for on-demand TLS request: {err}"),
972                                true,
973                              ))
974                              .await
975                              .unwrap_or_default();
976                          }
977                          continue;
978                        }
979                      },
980                    );
981                  }
982                  let endpoint_url = match hyper::Uri::from_parts(url_parts) {
983                    Ok(parsed) => parsed,
984                    Err(err) => {
985                      for acme_logger in global_configuration_clone
986                        .as_ref()
987                        .map_or(&vec![], |c| &c.observability.log_channels)
988                      {
989                        acme_logger
990                          .send(LogMessage::new(
991                            format!("Error while formatting the URL for on-demand TLS request: {err}"),
992                            true,
993                          ))
994                          .await
995                          .unwrap_or_default();
996                      }
997                      continue;
998                    }
999                  };
1000                  let ask_closure = async {
1001                    let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
1002                      .build::<_, http_body_util::Empty<hyper::body::Bytes>>(
1003                      hyper_rustls::HttpsConnectorBuilder::new()
1004                        .with_tls_config(
1005                          (if !on_demand_tls_ask_endpoint_verify {
1006                            ClientConfig::builder_with_provider(crypto_provider.clone())
1007                              .with_safe_default_protocol_versions()?
1008                              .dangerous()
1009                              .with_custom_certificate_verifier(Arc::new(NoServerVerifier::new()))
1010                          } else if let Ok(client_config) = BuilderVerifierExt::with_platform_verifier(
1011                            ClientConfig::builder_with_provider(crypto_provider.clone())
1012                              .with_safe_default_protocol_versions()?,
1013                          ) {
1014                            client_config
1015                          } else {
1016                            ClientConfig::builder_with_provider(crypto_provider.clone())
1017                              .with_safe_default_protocol_versions()?
1018                              .with_webpki_verifier(
1019                                WebPkiServerVerifier::builder(Arc::new(rustls::RootCertStore {
1020                                  roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
1021                                }))
1022                                .build()?,
1023                              )
1024                          })
1025                          .with_no_client_auth(),
1026                        )
1027                        .https_or_http()
1028                        .enable_http1()
1029                        .enable_http2()
1030                        .build(),
1031                    );
1032                    let request = hyper::Request::builder()
1033                      .method(hyper::Method::GET)
1034                      .uri(endpoint_url)
1035                      .body(http_body_util::Empty::<hyper::body::Bytes>::new())?;
1036                    let response = client.request(request).await?;
1037
1038                    Ok::<_, Box<dyn Error + Send + Sync>>(response.status().is_success())
1039                  };
1040                  match ask_closure.await {
1041                    Ok(true) => (),
1042                    Ok(false) => {
1043                      for acme_logger in global_configuration_clone
1044                        .as_ref()
1045                        .map_or(&vec![], |c| &c.observability.log_channels)
1046                      {
1047                        acme_logger
1048                          .send(LogMessage::new(
1049                            format!(
1050                              "The TLS certificate cannot be issued for \"{}\" hostname",
1051                              &received_data.0
1052                            ),
1053                            true,
1054                          ))
1055                          .await
1056                          .unwrap_or_default();
1057                      }
1058                      continue;
1059                    }
1060                    Err(err) => {
1061                      for acme_logger in global_configuration_clone
1062                        .as_ref()
1063                        .map_or(&vec![], |c| &c.observability.log_channels)
1064                      {
1065                        acme_logger
1066                          .send(LogMessage::new(
1067                            format!(
1068                              "Error while determining if the TLS certificate can be issued for \"{}\" hostname: {err}",
1069                              &received_data.0
1070                            ),
1071                            true,
1072                          ))
1073                          .await
1074                          .unwrap_or_default();
1075                      }
1076                      continue;
1077                    }
1078                  }
1079                }
1080                if existing_combinations.contains(&received_data) {
1081                  continue;
1082                } else {
1083                  existing_combinations.insert(received_data.clone());
1084                }
1085                let (sni_hostname, port) = received_data;
1086                let acme_configs_mutex = acme_configs_mutex.clone();
1087                let acme_on_demand_configs = acme_on_demand_configs.clone();
1088                let memory_acme_account_cache_data = memory_acme_account_cache_data.clone();
1089                let prevent_file_race_conditions_mutex = prevent_file_race_conditions_mutex.clone();
1090                tokio::spawn(async move {
1091                  for acme_on_demand_config in acme_on_demand_configs.iter() {
1092                    if match_hostname(acme_on_demand_config.sni_hostname.as_deref(), Some(&sni_hostname))
1093                      && acme_on_demand_config.port == port
1094                    {
1095                      let mutex_guard = prevent_file_race_conditions_mutex.lock().await;
1096                      add_domain_to_cache(acme_on_demand_config, &sni_hostname)
1097                        .await
1098                        .unwrap_or_default();
1099                      drop(mutex_guard);
1100
1101                      acme_configs_mutex.lock().await.push(
1102                        convert_on_demand_config(
1103                          acme_on_demand_config,
1104                          sni_hostname.clone(),
1105                          memory_acme_account_cache_data,
1106                        )
1107                        .await,
1108                      );
1109                      break;
1110                    }
1111                  }
1112                });
1113              }
1114            });
1115          }
1116
1117          let error_logger = ErrorLogger::new_multiple(
1118            global_configuration_clone
1119              .as_ref()
1120              .map_or(vec![], |c| c.observability.log_channels.clone()),
1121          );
1122          loop {
1123            for acme_config in &mut *acme_configs_mutex.lock().await {
1124              if let Err(acme_error) = provision_certificate(acme_config, &error_logger).await {
1125                error_logger
1126                  .log(&format!("Error while obtaining a TLS certificate: {acme_error}"))
1127                  .await
1128              }
1129            }
1130            tokio::time::sleep(Duration::from_secs(10)).await;
1131          }
1132        });
1133      }
1134
1135      // If HTTP/1.1 isn't enabled, don't listen to non-encrypted ports
1136      if !protocols.contains(&"h1") {
1137        nonencrypted_ports.clear();
1138      }
1139
1140      for tls_port in tls_ports.keys() {
1141        if nonencrypted_ports.contains(tls_port) {
1142          nonencrypted_ports.remove(tls_port);
1143        }
1144      }
1145
1146      // Create TLS server configurations
1147      let mut quic_tls_configs = HashMap::new();
1148      let mut tls_configs = HashMap::new();
1149      let mut acme_tls_alpn_01_configs = HashMap::new();
1150      for (tls_port, sni_resolver) in tls_ports.into_iter() {
1151        let enable_ocsp_stapling = global_configuration
1152          .as_ref()
1153          .and_then(|c| get_value!("ocsp_stapling", c))
1154          .and_then(|v| v.as_bool())
1155          .unwrap_or(true);
1156        let resolver: Arc<dyn ResolvesServerCert> = if enable_ocsp_stapling {
1157          // The `ocsp_stapler` crate is dependent on Tokio, so we create a stapler in the Tokio runtime...
1158          // If this wasn't wrapped in a Tokio runtime, creation of a OCSP stapler would just cause a panic.
1159          let stapler =
1160            secondary_runtime_ref.block_on(async move { ocsp_stapler::Stapler::new(Arc::new(sni_resolver)) });
1161          if let Some(certified_keys_to_preload) = certified_keys_to_preload.get(&tls_port) {
1162            for certified_key in certified_keys_to_preload {
1163              stapler.preload(certified_key.clone());
1164            }
1165          }
1166          Arc::new(stapler)
1167        } else {
1168          Arc::new(sni_resolver)
1169        };
1170        let mut tls_config = tls_config_builder_wants_server_cert
1171          .clone()
1172          .with_cert_resolver(resolver);
1173        if protocols.contains(&"h3") {
1174          // TLS configuration used for QUIC listene
1175          let mut quic_tls_config = tls_config.clone();
1176          quic_tls_config.max_early_data_size = u32::MAX;
1177          quic_tls_config.alpn_protocols.insert(0, b"h3-29".to_vec());
1178          quic_tls_config.alpn_protocols.insert(0, b"h3".to_vec());
1179          quic_tls_configs.insert(tls_port, Arc::new(quic_tls_config));
1180        }
1181        if protocols.contains(&"h1") {
1182          tls_config.alpn_protocols.insert(0, b"http/1.0".to_vec());
1183          tls_config.alpn_protocols.insert(0, b"http/1.1".to_vec());
1184        }
1185        if protocols.contains(&"h2") {
1186          tls_config.alpn_protocols.insert(0, b"h2".to_vec());
1187        }
1188        tls_configs.insert(tls_port, Arc::new(tls_config));
1189      }
1190      for (tls_port, sni_resolver) in acme_tls_alpn_01_resolvers.into_iter() {
1191        let mut tls_config = tls_config_builder_wants_server_cert
1192          .clone()
1193          .with_cert_resolver(Arc::new(sni_resolver));
1194        tls_config.alpn_protocols = vec![ACME_TLS_ALPN_NAME.to_vec()];
1195        acme_tls_alpn_01_configs.insert(tls_port, Arc::new(tls_config));
1196      }
1197
1198      // Process metrics initialization
1199      #[cfg(any(target_os = "linux", target_os = "android"))]
1200      if let Some(metrics_channels) = global_configuration
1201        .as_ref()
1202        .map(|c| &c.observability.metric_channels)
1203        .cloned()
1204      {
1205        secondary_runtime_ref.spawn(async move {
1206          use ferron_common::observability::{Metric, MetricAttributeValue, MetricType, MetricValue};
1207
1208          let mut previous_instant = std::time::Instant::now();
1209          let mut previous_cpu_user_time = 0.0;
1210          let mut previous_cpu_system_time = 0.0;
1211          let mut previous_rss = 0;
1212          let mut previous_vms = 0;
1213          loop {
1214            // Sleep for 1 second
1215            tokio::time::sleep(Duration::from_secs(1)).await;
1216
1217            if let Ok(Ok(stat)) =
1218              tokio::task::spawn_blocking(|| procfs::process::Process::myself().and_then(|p| p.stat())).await
1219            {
1220              let cpu_user_time = stat.utime as f64 / procfs::ticks_per_second() as f64;
1221              let cpu_system_time = stat.stime as f64 / procfs::ticks_per_second() as f64;
1222              let cpu_user_time_increase = cpu_user_time - previous_cpu_user_time;
1223              let cpu_system_time_increase = cpu_system_time - previous_cpu_system_time;
1224              previous_cpu_user_time = cpu_user_time;
1225              previous_cpu_system_time = cpu_system_time;
1226
1227              let rss = stat.rss * procfs::page_size();
1228              let rss_diff = rss as i64 - previous_rss as i64;
1229              let vms_diff = stat.vsize as i64 - previous_vms as i64;
1230              previous_rss = rss;
1231              previous_vms = stat.vsize;
1232
1233              let elapsed = previous_instant.elapsed().as_secs_f64();
1234              previous_instant = std::time::Instant::now();
1235
1236              let cpu_user_utilization = cpu_user_time_increase / (elapsed * available_parallelism as f64);
1237              let cpu_system_utilization = cpu_system_time_increase / (elapsed * available_parallelism as f64);
1238
1239              for metrics_sender in &metrics_channels {
1240                metrics_sender
1241                  .send(Metric::new(
1242                    "process.cpu.time",
1243                    vec![("cpu.mode", MetricAttributeValue::String("user".to_string()))],
1244                    MetricType::Counter,
1245                    MetricValue::F64(cpu_user_time_increase),
1246                    Some("s"),
1247                    Some("Total CPU seconds broken down by different states."),
1248                  ))
1249                  .await
1250                  .unwrap_or_default();
1251
1252                metrics_sender
1253                  .send(Metric::new(
1254                    "process.cpu.time",
1255                    vec![("cpu.mode", MetricAttributeValue::String("system".to_string()))],
1256                    MetricType::Counter,
1257                    MetricValue::F64(cpu_system_time_increase),
1258                    Some("s"),
1259                    Some("Total CPU seconds broken down by different states."),
1260                  ))
1261                  .await
1262                  .unwrap_or_default();
1263
1264                metrics_sender
1265                  .send(Metric::new(
1266                    "process.cpu.utilization",
1267                    vec![("cpu.mode", MetricAttributeValue::String("user".to_string()))],
1268                    MetricType::Gauge,
1269                    MetricValue::F64(cpu_user_utilization),
1270                    Some("1"),
1271                    Some(
1272                      "Difference in process.cpu.time since the last measurement, \
1273                       divided by the elapsed time and number of CPUs available to the process.",
1274                    ),
1275                  ))
1276                  .await
1277                  .unwrap_or_default();
1278
1279                metrics_sender
1280                  .send(Metric::new(
1281                    "process.cpu.utilization",
1282                    vec![("cpu.mode", MetricAttributeValue::String("system".to_string()))],
1283                    MetricType::Gauge,
1284                    MetricValue::F64(cpu_system_utilization),
1285                    Some("1"),
1286                    Some(
1287                      "Difference in process.cpu.time since the last measurement, \
1288                      divided by the elapsed time and number of CPUs available to the process.",
1289                    ),
1290                  ))
1291                  .await
1292                  .unwrap_or_default();
1293
1294                metrics_sender
1295                  .send(Metric::new(
1296                    "process.memory.usage",
1297                    vec![],
1298                    MetricType::UpDownCounter,
1299                    MetricValue::I64(rss_diff),
1300                    Some("By"),
1301                    Some("The amount of physical memory in use."),
1302                  ))
1303                  .await
1304                  .unwrap_or_default();
1305
1306                metrics_sender
1307                  .send(Metric::new(
1308                    "process.memory.virtual",
1309                    vec![],
1310                    MetricType::UpDownCounter,
1311                    MetricValue::I64(vms_diff),
1312                    Some("By"),
1313                    Some("The amount of committed virtual memory."),
1314                  ))
1315                  .await
1316                  .unwrap_or_default();
1317              }
1318            }
1319          }
1320        });
1321      }
1322
1323      let (listener_handler_tx, listener_handler_rx) = &**LISTENER_HANDLER_CHANNEL;
1324      let mut tcp_listeners = TCP_LISTENERS
1325        .lock()
1326        .map_err(|_| anyhow::anyhow!("Can't access the TCP listeners"))?;
1327      let mut quic_listeners = QUIC_LISTENERS
1328        .lock()
1329        .map_err(|_| anyhow::anyhow!("Can't access the QUIC listeners"))?;
1330      let mut listened_socket_addresses = Vec::new();
1331      let mut quic_listened_socket_addresses = Vec::new();
1332      let listen_ip_addr = global_configuration
1333        .as_deref()
1334        .and_then(|c| get_value!("listen_ip", c))
1335        .and_then(|v| v.as_str())
1336        .map_or(Ok(IpAddr::V6(Ipv6Addr::UNSPECIFIED)), |a| a.parse())
1337        .map_err(|_| anyhow::anyhow!("Invalid IP address to listen to"))?;
1338      for (tcp_port, encrypted) in nonencrypted_ports
1339        .iter()
1340        .map(|p| (*p, false))
1341        .chain(tls_configs.keys().map(|p| (*p, true)))
1342      {
1343        let socket_address = SocketAddr::new(listen_ip_addr, tcp_port);
1344        listened_socket_addresses.push((socket_address, encrypted));
1345      }
1346      for (quic_port, quic_tls_config) in quic_tls_configs.into_iter() {
1347        let socket_address = SocketAddr::new(listen_ip_addr, quic_port);
1348        quic_listened_socket_addresses.push((socket_address, quic_tls_config));
1349      }
1350
1351      let enable_uring = global_configuration
1352        .as_deref()
1353        .and_then(|c| get_value!("io_uring", c))
1354        .and_then(|v| v.as_bool());
1355      let mut uring_enabled_locked = URING_ENABLED
1356        .lock()
1357        .map_err(|_| anyhow::anyhow!("Can't access the enabled `io_uring` option"))?;
1358      let mut tcp_listener_socketaddrs_to_remove = Vec::new();
1359      let mut quic_listener_socketaddrs_to_remove = Vec::new();
1360      for (key, value) in &*tcp_listeners {
1361        if enable_uring != *uring_enabled_locked
1362          || (!listened_socket_addresses.contains(&(*key, true)) && !listened_socket_addresses.contains(&(*key, false)))
1363        {
1364          // Shut down the TCP listener
1365          value.cancel();
1366
1367          // Push the the TCP listener address to remove
1368          tcp_listener_socketaddrs_to_remove.push(*key);
1369        }
1370      }
1371      for (key, value) in &*quic_listeners {
1372        let mut contains = false;
1373        for key2 in &quic_listened_socket_addresses {
1374          if key2.0 == *key {
1375            contains = true;
1376            break;
1377          }
1378        }
1379        if !contains {
1380          // Shut down the QUIC listener
1381          value.0.cancel();
1382
1383          // Push the the QUIC listener address to remove
1384          quic_listener_socketaddrs_to_remove.push(*key);
1385        }
1386      }
1387      *uring_enabled_locked = enable_uring;
1388      drop(uring_enabled_locked);
1389
1390      for key_to_remove in tcp_listener_socketaddrs_to_remove {
1391        // Remove the TCP listener
1392        tcp_listeners.remove(&key_to_remove);
1393      }
1394
1395      for key_to_remove in quic_listener_socketaddrs_to_remove {
1396        // Remove the QUIC listener
1397        quic_listeners.remove(&key_to_remove);
1398      }
1399
1400      // Get a global logger for listeners
1401      let (global_logging_tx, global_logging_rx) = &**LISTENER_LOGGING_CHANNEL;
1402      let global_logger = if global_configuration
1403        .as_ref()
1404        .is_none_or(|c| c.observability.log_channels.is_empty())
1405      {
1406        None
1407      } else {
1408        let global_configuration_clone = global_configuration.clone();
1409        secondary_runtime_ref.spawn(async move {
1410          while let Ok(log_message) = global_logging_rx.recv().await {
1411            for logging_tx in global_configuration_clone
1412              .as_ref()
1413              .map_or(&vec![], |c| &c.observability.log_channels)
1414            {
1415              logging_tx.send(log_message.clone()).await.unwrap_or_default();
1416            }
1417          }
1418        });
1419        Some(global_logging_tx.clone())
1420      };
1421
1422      let (io_uring_disabled_tx, io_uring_disabled_rx) = async_channel::unbounded();
1423      if let Some(global_logger) = &global_logger {
1424        let global_logger = global_logger.clone();
1425        secondary_runtime_ref.spawn(async move {
1426          while let Ok(err) = io_uring_disabled_rx.recv().await {
1427            if let Some(err) = err {
1428              global_logger
1429                .send(LogMessage::new(
1430                  format!("Can't configure io_uring: {err}. Ferron may run with io_uring disabled."),
1431                  true,
1432                ))
1433                .await
1434                .unwrap_or_default();
1435              break;
1436            }
1437          }
1438
1439          io_uring_disabled_rx.close();
1440        });
1441      } else {
1442        io_uring_disabled_rx.close();
1443      }
1444
1445      // Spawn request handler threads
1446      let mut handler_shutdown_channels = Vec::new();
1447      for _ in 0..available_parallelism {
1448        handler_shutdown_channels.push(create_http_handler(
1449          server_configurations.clone(),
1450          listener_handler_rx.clone(),
1451          enable_uring,
1452          tls_configs.clone(),
1453          !quic_listened_socket_addresses.is_empty(),
1454          acme_tls_alpn_01_configs.clone(),
1455          acme_http_01_resolvers.clone(),
1456          enable_proxy_protocol,
1457          io_uring_disabled_tx.clone(),
1458        )?);
1459      }
1460
1461      // Error out, if server is configured to listen to no port
1462      if listened_socket_addresses.is_empty() && quic_listened_socket_addresses.is_empty() {
1463        Err(anyhow::anyhow!("The server is configured to listen to no port"))?
1464      }
1465
1466      let tcp_send_buffer_size = global_configuration
1467        .as_deref()
1468        .and_then(|c| get_value!("tcp_send_buffer", c))
1469        .and_then(|v| v.as_i128())
1470        .map(|v| v as usize);
1471      let tcp_recv_buffer_size = global_configuration
1472        .as_deref()
1473        .and_then(|c| get_value!("tcp_recv_buffer", c))
1474        .and_then(|v| v.as_i128())
1475        .map(|v| v as usize);
1476      for (socket_address, encrypted) in listened_socket_addresses {
1477        if let std::collections::hash_map::Entry::Vacant(e) = tcp_listeners.entry(socket_address) {
1478          // Create a TCP listener
1479          e.insert(create_tcp_listener(
1480            socket_address,
1481            encrypted,
1482            listener_handler_tx.clone(),
1483            enable_uring,
1484            global_logger.clone(),
1485            first_startup,
1486            (tcp_send_buffer_size, tcp_recv_buffer_size),
1487            io_uring_disabled_tx.clone(),
1488          )?);
1489        }
1490      }
1491
1492      // Drop TCP listener mutex guard
1493      drop(tcp_listeners);
1494
1495      for (socket_address, tls_config) in quic_listened_socket_addresses {
1496        if let Some(quic_listener_entry) = quic_listeners.get(&socket_address) {
1497          // Replace the TLS configuration in the QUIC listener
1498          let (_, tls_quic_listener) = quic_listener_entry;
1499          tls_quic_listener.send_blocking(tls_config).unwrap_or_default();
1500        } else {
1501          // Create a QUIC listener
1502          quic_listeners.insert(
1503            socket_address,
1504            create_quic_listener(
1505              socket_address,
1506              tls_config,
1507              listener_handler_tx.clone(),
1508              global_logger.clone(),
1509              first_startup,
1510            )?,
1511          );
1512        }
1513      }
1514
1515      // Drop QUIC listener mutex guard
1516      drop(quic_listeners);
1517
1518      let shutdown_result = handle_shutdown_signals(secondary_runtime_ref);
1519
1520      Ok::<_, Box<dyn Error + Send + Sync>>((shutdown_result, handler_shutdown_channels))
1521    };
1522
1523    match execute_rest() {
1524      Ok((to_restart, handler_shutdown_channels)) => {
1525        if to_restart {
1526          old_runtime = Some((handler_shutdown_channels, secondary_runtime));
1527          first_startup = false;
1528          println!("Reloading the server configuration...");
1529        } else {
1530          for shutdown in handler_shutdown_channels {
1531            shutdown.cancel();
1532          }
1533          drop(secondary_runtime);
1534          break;
1535        }
1536      }
1537      Err(err) => {
1538        for logging_tx in global_configuration_clone
1539          .as_ref()
1540          .map_or(&vec![], |c| &c.observability.log_channels)
1541        {
1542          logging_tx
1543            .send_blocking(LogMessage::new(err.to_string(), true))
1544            .unwrap_or_default();
1545        }
1546        std::thread::sleep(Duration::from_millis(100));
1547        Err(err)?
1548      }
1549    }
1550  }
1551  Ok(())
1552}
1553
1554fn obtain_configuration_adapters() -> (
1555  HashMap<String, Box<dyn ConfigurationAdapter + Send + Sync>>,
1556  Vec<&'static str>,
1557) {
1558  // Configuration adapters
1559  let mut configuration_adapters: HashMap<String, Box<dyn ConfigurationAdapter + Send + Sync>> = HashMap::new();
1560  let mut all_adapters = Vec::new();
1561
1562  // Configuration adapter registration macro
1563  macro_rules! register_configuration_adapter {
1564    ($name:literal, $adapter:expr) => {
1565      configuration_adapters.insert($name.to_string(), Box::new($adapter));
1566      all_adapters.push($name);
1567    };
1568  }
1569
1570  // Register configuration adapters
1571  register_configuration_adapter!("kdl", config::adapters::kdl::KdlConfigurationAdapter::new());
1572  #[cfg(feature = "config-yaml-legacy")]
1573  register_configuration_adapter!(
1574    "yaml-legacy",
1575    config::adapters::yaml_legacy::YamlLegacyConfigurationAdapter::new()
1576  );
1577  #[cfg(feature = "config-docker-auto")]
1578  register_configuration_adapter!(
1579    "docker-auto",
1580    config::adapters::docker_auto::DockerAutoConfigurationAdapter::new()
1581  );
1582
1583  (configuration_adapters, all_adapters)
1584}
1585
1586/// Determines the default configuration adapter
1587#[cfg(feature = "config-yaml-legacy")]
1588fn determine_default_configuration_adapter(path: &Path) -> &'static str {
1589  match path
1590    .extension()
1591    .and_then(|s| s.to_str())
1592    .map(|s| s.to_lowercase())
1593    .as_deref()
1594  {
1595    Some("yaml") | Some("yml") => "yaml-legacy",
1596    _ => "kdl",
1597  }
1598}
1599
1600/// Determines the default configuration adapter
1601#[cfg(not(feature = "config-yaml-legacy"))]
1602fn determine_default_configuration_adapter(_path: &Path) -> &'static str {
1603  "kdl"
1604}
1605
1606/// Parses the command-line arguments
1607fn parse_arguments(all_adapters: Vec<&'static str>) -> ArgMatches {
1608  Command::new("Ferron")
1609    .about("A fast, memory-safe web server written in Rust")
1610    .arg(
1611      Arg::new("config")
1612        .long("config")
1613        .short('c')
1614        .help("The path to the server configuration file")
1615        .action(ArgAction::Set)
1616        .default_value("./ferron.kdl")
1617        .value_parser(PathBuf::from_str),
1618    )
1619    .arg(
1620      Arg::new("config-adapter")
1621        .long("config-adapter")
1622        .help("The configuration adapter to use")
1623        .action(ArgAction::Set)
1624        .required(false)
1625        .value_parser(all_adapters),
1626    )
1627    .arg(
1628      Arg::new("module-config")
1629        .long("module-config")
1630        .help("Prints the used compile-time module configuration (`ferron-build.yaml` or `ferron-build-override.yaml` in the Ferron source) and exits")
1631        .action(ArgAction::SetTrue)
1632    )
1633    .arg(
1634      Arg::new("version")
1635        .long("version")
1636        .short('V')
1637        .help("Print version and build information")
1638        .action(ArgAction::SetTrue)
1639    )
1640    .get_matches()
1641}
1642
1643/// The main entry point of the application
1644fn main() {
1645  // Set the panic handler
1646  setup_panic!(Metadata::new("Ferron", env!("CARGO_PKG_VERSION"))
1647    .homepage("https://ferron.sh")
1648    .support("- Send an email message to hello@ferron.sh"));
1649
1650  // Obtain the configuration adapters
1651  let (configuration_adapters, all_adapters) = obtain_configuration_adapters();
1652
1653  // Parse command-line arguments
1654  let args = parse_arguments(all_adapters);
1655
1656  if args.get_flag("module-config") {
1657    // Dump the used compile-time module configuration and exit
1658    println!("{}", ferron_load_modules::FERRON_BUILD_YAML);
1659    return;
1660  } else if args.get_flag("version") {
1661    // Print the server version and build information
1662    println!("Ferron {}", build::PKG_VERSION);
1663    println!("  Compiled on: {}", build::BUILD_TIME);
1664    println!("  Git commit: {}", build::COMMIT_HASH);
1665    println!("  Build target: {}", build::BUILD_TARGET);
1666    println!("  Rust version: {}", build::RUST_VERSION);
1667    println!("  Build host: {}", build::BUILD_OS);
1668    if shadow_rs::is_debug() {
1669      println!("WARNING: This is a debug build. It is not recommended for production use.");
1670    }
1671    return;
1672  }
1673
1674  // Start the server!
1675  match before_starting_server(args, configuration_adapters) {
1676    Ok(_) => (),
1677    Err(err) => {
1678      eprintln!("Error while running a server: {err}");
1679      std::process::exit(1);
1680    }
1681  };
1682}