ferron/
main.rs

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