if (::arg().mustDo("webserver")) {
extern void serveRustWeb();
+ cerr << "CALL serveRustWeb" << endl;
serveRustWeb();
}
if (::arg().mustDo("webserver")) {
extern void serveRustWeb();
+ cerr << "WS is CALLED " << endl;
serveRustWeb();
}
-
+ else {
+ cerr << "WS is FALSE " << endl;
+ }
for (auto& tInfo : RecThreadInfo::infos()) {
tInfo.thread.join();
if (tInfo.exitCode != 0) {
string reloadZoneConfiguration(bool yaml)
{
- std::shared_ptr<SyncRes::domainmap_t> original = SyncRes::getDomainMap();
auto log = g_slog->withName("config");
string configname = ::arg()["config-dir"] + "/recursor";
oldAndNewDomains.insert(entry.first);
}
- if (original) {
- for (const auto& entry : *original) {
- oldAndNewDomains.insert(entry.first);
+ extern LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // XXX
+ {
+ auto lock = g_initialDomainMap.lock();
+ if (*lock) {
+ for (const auto& entry : **lock) {
+ oldAndNewDomains.insert(entry.first);
+ }
}
}
// these explicitly-named captures should not be necessary, as lambda
// capture of tuple-like structured bindings is permitted, but some
// compilers still don't allow it
- broadcastFunction([dmap = std::move(newDomainMap)] { return pleaseUseNewSDomainsMap(dmap); });
- broadcastFunction([nsset = std::move(newNotifySet)] { return pleaseSupplantAllowNotifyFor(nsset); });
+ broadcastFunction([dmap = newDomainMap] { return pleaseUseNewSDomainsMap(dmap); });
+ broadcastFunction([nsset = newNotifySet] { return pleaseSupplantAllowNotifyFor(nsset); });
// Wipe the caches *after* the new auth domain info has been set
// up, as a query during setting up might fill the caches
for (const auto& entry : oldAndNewDomains) {
wipeCaches(entry, true, 0xffff);
}
- extern LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // XXX
- *g_initialDomainMap.lock() = newDomainMap;
+ *g_initialDomainMap.lock() = std::move(newDomainMap);
extern LockGuarded<std::shared_ptr<notifyset_t>> g_initialAllowNotifyFor; // XXX
- *g_initialAllowNotifyFor.lock() = newNotifySet;
+ *g_initialAllowNotifyFor.lock() = std::move(newNotifySet);
return "ok\n";
}
catch (const std::exception& e) {
ListDNSTapFrameStreamServers = auto()
ListDNSTapNODFrameStreamServers = auto()
ListForwardZones = auto()
+ ListForwardingCatalogZones = auto()
+ ListIncomingWSConfigs = auto()
ListNegativeTrustAnchors = auto()
ListProtobufServers = auto()
ListProxyMappings = auto()
ListSubnets = auto()
ListTrustAnchors = auto()
ListZoneToCaches = auto()
- ListForwardingCatalogZones = auto()
String = auto()
Uint64 = auto()
listOfStructuredTypes = (LType.ListAuthZones, LType.ListForwardZones, LType.ListTrustAnchors, LType.ListNegativeTrustAnchors,
LType.ListProtobufServers, LType.ListDNSTapFrameStreamServers, LType.ListDNSTapNODFrameStreamServers,
LType.ListSortLists, LType.ListRPZs, LType.ListZoneToCaches, LType.ListAllowedAdditionalQTypes,
- LType.ListProxyMappings, LType.ListForwardingCatalogZones)
+ LType.ListProxyMappings, LType.ListForwardingCatalogZones, LType.ListIncomingWSConfigs)
def get_olddoc_typename(typ):
"""Given a type from table.py, return the old-style type name"""
return 'Comma separated list of \'zonename=IP\' pairs'
if typ == LType.ListAuthZones:
return 'Comma separated list of \'zonename=filename\' pairs'
- return 'Unknown' + str(typ)
+ return 'Unknown1' + str(typ)
def get_newdoc_typename(typ):
"""Given a type from table.py, return the new-style type name"""
return 'Sequence of `ProxyMapping`_'
if typ == LType.ListForwardingCatalogZones:
return 'Sequence of `ForwardingCatalogZone`_'
- return 'Unknown' + str(typ)
+ return 'Unknown2' + str(typ)
def get_default_olddoc_value(typ, val):
"""Given a type and a value from table.py return the old doc representation of the value"""
if typeName.startswith('List') and typeName.endswith('s'):
baseName = typeName[4:len(typeName) - 1]
return baseName
- return 'Unknown: ' + typeName
+ return 'Unknown3: ' + typeName
def get_rust_type(typ):
"""Determine which Rust type is used for a logical type"""
groups: Vec<FCZDefault>,
}
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+pub struct IncomingTLS {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ certificate: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ key: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ password: String,
+}
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+pub struct IncomingWSConfig {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ addresses: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tls: IncomingTLS,
+}
+
// Two structs used to generated YAML based on a vector of name to value mappings
// Cannot use Enum as CXX has only very basic Enum support
struct Value {
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "addr2line"
"pin-utils",
]
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
[[package]]
name = "gimli"
version = "0.31.1"
"pin-project-lite",
"smallvec",
"tokio",
+ "want",
+]
+
+[[package]]
+name = "hyper-rustls"
+version = "0.27.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
+dependencies = [
+ "futures-util",
+ "http",
+ "hyper",
+ "hyper-util",
+ "rustls",
+ "rustls-pki-types",
+ "tokio",
+ "tokio-rustls",
+ "tower-service",
]
[[package]]
checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
dependencies = [
"bytes",
+ "futures-channel",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
+ "socket2",
"tokio",
+ "tower-service",
+ "tracing",
]
[[package]]
"proc-macro2",
]
+[[package]]
+name = "ring"
+version = "0.17.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "getrandom",
+ "libc",
+ "spin",
+ "untrusted",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+[[package]]
+name = "rustls"
+version = "0.23.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
+dependencies = [
+ "once_cell",
+ "ring",
+ "rustls-pki-types",
+ "rustls-webpki",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
+dependencies = [
+ "rustls-pki-types",
+]
+
+[[package]]
+name = "rustls-pki-types"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
+
+[[package]]
+name = "rustls-webpki"
+version = "0.102.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
+dependencies = [
+ "ring",
+ "rustls-pki-types",
+ "untrusted",
+]
+
[[package]]
name = "ryu"
version = "1.0.18"
"form_urlencoded",
"http-body-util",
"hyper",
+ "hyper-rustls",
"hyper-util",
"ipnet",
"once_cell",
+ "rustls",
+ "rustls-pemfile",
+ "rustls-pki-types",
"serde",
"serde_yml",
"tokio",
+ "tokio-rustls",
]
[[package]]
"windows-sys 0.52.0",
]
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
[[package]]
name = "syn"
-version = "2.0.77"
+version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [
"proc-macro2",
"quote",
"windows-sys 0.52.0",
]
+[[package]]
+name = "tokio-rustls"
+version = "0.26.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
+dependencies = [
+ "rustls",
+ "tokio",
+]
+
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
+[[package]]
+name = "tracing"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+dependencies = [
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+[[package]]
+name = "untrusted"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "zeroize"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
hyper-util = { version = "0.1", features = ["tokio"]}
bytes = "1.8"
form_urlencoded = "1.2"
+hyper-rustls = { version = "0.27", default-features = false }
+rustls = { version = "0.23", default-features = false, features = ["ring"] }
+rustls-pemfile = "2.2"
+pki-types = { package = "rustls-pki-types", version = "1.10" }
+tokio-rustls = { version = "0.26", default-features = false }
[build-dependencies]
cxx-build = "1.0"
$CARGO build --release $RUST_TARGET --target-dir=$builddir/target --manifest-path $srcdir/Cargo.toml
-cp -p target/$RUSTC_TARGET_ARCH/release/libsettings.a $builddir/settings/rust/libsettings.a
-cp -p target/$RUSTC_TARGET_ARCH/cxxbridge/settings/src/lib.rs.h $srcdir/lib.rs.h
-cp -p target/$RUSTC_TARGET_ARCH/cxxbridge/settings/src/lib.rs.h $builddir/settings/rust/lib.rs.h
-cp -p target/$RUSTC_TARGET_ARCH/cxxbridge/rust/cxx.h $srcdir/cxx.h
-cp -p target/$RUSTC_TARGET_ARCH/cxxbridge/rust/cxx.h $builddir/settings/rust/cxx.h
+cp -vp target/$RUSTC_TARGET_ARCH/release/libsettings.a $builddir/settings/rust/libsettings.a
+cp -vp target/$RUSTC_TARGET_ARCH/cxxbridge/settings/src/lib.rs.h $srcdir/lib.rs.h
+cp -vp target/$RUSTC_TARGET_ARCH/cxxbridge/settings/src/lib.rs.h $builddir/settings/rust/lib.rs.h
+cp -vp target/$RUSTC_TARGET_ARCH/cxxbridge/rust/cxx.h $srcdir/cxx.h
+cp -vp target/$RUSTC_TARGET_ARCH/cxxbridge/rust/cxx.h $builddir/settings/rust/cxx.h
+cp -vp target/$RUSTC_TARGET_ARCH/cxxbridge/settings/src/web.rs.h $srcdir/web.rs.h
+cp -vp target/$RUSTC_TARGET_ARCH/cxxbridge/settings/src/web.rs.h $builddir/settings/rust/web.rs.h
*/
#pragma once
+#include <memory>
+
#include "rust/cxx.h"
#include "credentials.hh"
struct KeyValue;
struct Request;
struct Response;
+struct IncomingWSConfig;
template <typename A>
class Wrapper
}
}
+impl Default for IncomingTLS {
+ fn default() -> Self {
+ let deserialized: IncomingTLS = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+impl Default for IncomingWSConfig {
+ fn default() -> Self {
+ let deserialized: IncomingWSConfig = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
pub fn validate_socket_address(field: &str, val: &String) -> Result<(), ValidationError> {
let sa = SocketAddr::from_str(val);
if sa.is_err() {
}
}
+impl IncomingWSConfig {
+ pub fn validate(&self, _field: &str) -> Result<(), ValidationError> {
+ // XXX
+ Ok(())
+ }
+}
+
#[allow(clippy::ptr_arg)] //# Avoids creating a rust::Slice object on the C++ side.
pub fn validate_auth_zones(field: &str, vec: &Vec<AuthZone>) -> Result<(), ValidationError> {
validate_vec(field, vec, |field, element| element.validate(field))
Ok(rust_response)
}
-async fn serveweb_async(listener: TcpListener, ctx: Arc<Context>) -> MyResult<()> {
-
- // We start a loop to continuously accept incoming connections
- loop {
- let ctx = Arc::clone(&ctx);
- let (stream, _) = listener.accept().await?;
-
- match stream.peer_addr() {
- Ok(address) => {
- eprintln!("Peer: {:?}", address);
- let combo = rustweb::comboaddress(&address.to_string());
- if !rustweb::matches(&ctx.acl, &combo) {
- eprintln!("No acl match! {:?}", address);
- continue;
+async fn serveweb_async(listener: TcpListener, config: crate::web::rustweb::IncomingTLS, ctx: Arc<Context>) -> MyResult<()> {
+
+ if !config.certificate.is_empty() {
+ let certs = load_certs(&config.certificate)?;
+ let key = load_private_key(&config.key)?;
+ let mut server_config = rustls::ServerConfig::builder()
+ .with_no_client_auth()
+ .with_single_cert(certs, key)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
+ server_config.alpn_protocols = vec![b"http/1.1".to_vec(), b"http/1.0".to_vec()]; // b"h2".to_vec()
+ let tls_acceptor = tokio_rustls::TlsAcceptor::from(Arc::new(server_config));
+ // We start a loop to continuously accept incoming connections
+ loop {
+ let ctx = Arc::clone(&ctx);
+ let (stream, _) = listener.accept().await?;
+
+ match stream.peer_addr() {
+ Ok(address) => {
+ eprintln!("Peer: {:?}", address);
+ let combo = rustweb::comboaddress(&address.to_string());
+ if !rustweb::matches(&ctx.acl, &combo) {
+ eprintln!("No acl match! {:?}", address);
+ continue;
+ }
+ }
+ Err(err) => {
+ eprintln!("Can't get: {:?}", err);
+ continue; // If we can't determine the peer address, don't
}
}
- Err(err) => {
- eprintln!("Can't get: {:?}", err);
- continue; // If we can't determine the peer address, don't
- }
+ // Use an adapter to access something implementing `tokio::io` traits as if they implement
+ // `hyper::rt` IO traits.
+ let tls_acceptor = tls_acceptor.clone();
+ let tls_stream = match tls_acceptor.accept(stream).await {
+ Ok(tls_stream) => tls_stream,
+ Err(err) => {
+ eprintln!("failed to perform tls handshake: {err:#}");
+ continue;
+ }
+ };
+ let io = TokioIo::new(tls_stream);
+ let fut =
+ http1::Builder::new().serve_connection(io, service_fn(move |req| {
+ let ctx = Arc::clone(&ctx);
+ process_request(req, ctx)
+ }));
+
+ // Spawn a tokio task to serve the request
+ tokio::task::spawn(async move {
+ // Finally, we bind the incoming connection to our `process_request` service
+ if let Err(err) = fut.await {
+ eprintln!("Error serving connection: {:?}", err);
+ }
+ });
}
- // Use an adapter to access something implementing `tokio::io` traits as if they implement
- // `hyper::rt` IO traits.
- let io = TokioIo::new(stream);
- let fut =
- http1::Builder::new().serve_connection(io, service_fn(move |req| {
- let ctx = Arc::clone(&ctx);
- process_request(req, ctx)
- }));
-
- // Spawn a tokio task to serve the request
- tokio::task::spawn(async move {
- // Finally, we bind the incoming connection to our `process_request` service
- if let Err(err) = fut.await {
- eprintln!("Error serving connection: {:?}", err);
+ }
+ else {
+ // We start a loop to continuously accept incoming connections
+ loop {
+ let ctx = Arc::clone(&ctx);
+ let (stream, _) = listener.accept().await?;
+
+ match stream.peer_addr() {
+ Ok(address) => {
+ eprintln!("Peer: {:?}", address);
+ let combo = rustweb::comboaddress(&address.to_string());
+ if !rustweb::matches(&ctx.acl, &combo) {
+ eprintln!("No acl match! {:?}", address);
+ continue;
+ }
+ }
+ Err(err) => {
+ eprintln!("Can't get: {:?}", err);
+ continue; // If we can't determine the peer address, don't
+ }
}
- });
+ let io = TokioIo::new(stream);
+ let fut =
+ http1::Builder::new().serve_connection(io, service_fn(move |req| {
+ let ctx = Arc::clone(&ctx);
+ process_request(req, ctx)
+ }));
+
+ // Spawn a tokio task to serve the request
+ tokio::task::spawn(async move {
+ // Finally, we bind the incoming connection to our `process_request` service
+ if let Err(err) = fut.await {
+ eprintln!("Error serving connection: {:?}", err);
+ }
+ });
+ }
}
}
-pub fn serveweb(addresses: &Vec<String>, urls: &[String], password_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, api_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, acl: cxx::UniquePtr<rustweb::NetmaskGroup>) -> Result<(), std::io::Error> {
+pub fn serveweb(incoming: &Vec<rustweb::IncomingWSConfig>, urls: &[String], password_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, api_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, acl: cxx::UniquePtr<rustweb::NetmaskGroup>) -> Result<(), std::io::Error> {
+ println!("SERVEWEB");
// Context, atomically reference counted
let ctx = Arc::new(Context {
urls: urls.to_vec(),
// For each listening address we spawn a tokio handler an then a single Posix thread is created that
// waits (forever) for all of them to complete by joining them all.
let mut set = JoinSet::new();
- for addr_str in addresses {
- let addr = match SocketAddr::from_str(addr_str) {
- Ok(val) => val,
- Err(err) => {
- let msg = format!("`{}' is not a IP:port combination: {}", addr_str, err);
- return Err(std::io::Error::new(ErrorKind::Other, msg));
- }
- };
+ for config in incoming {
+ println!("Config");
+ for addr_str in &config.addresses {
+ println!("Config Addr {}", addr_str);
+ let addr = match SocketAddr::from_str(addr_str) {
+ Ok(val) => val,
+ Err(err) => {
+ let msg = format!("`{}' is not a IP:port combination: {}", addr_str, err);
+ return Err(std::io::Error::new(ErrorKind::Other, msg));
+ }
+ };
- let listener = runtime.block_on(async { TcpListener::bind(addr).await });
- let ctx = Arc::clone(&ctx);
- match listener {
- Ok(val) => {
- println!("Listening on {}", addr);
- set.spawn_on(serveweb_async(val, ctx), runtime.handle());
- }
- Err(err) => {
- let msg = format!("Unable to bind web socket: {}", err);
- return Err(std::io::Error::new(ErrorKind::Other, msg));
+ let listener = runtime.block_on(async { TcpListener::bind(addr).await });
+ let ctx = Arc::clone(&ctx);
+ match listener {
+ Ok(val) => {
+ let tls = crate::web::rustweb::IncomingTLS {
+ certificate: config.tls.certificate.clone(),
+ key: config.tls.key.clone(),
+ password: config.tls.password.clone(),
+ };
+ println!("Listening on {}", addr);
+ set.spawn_on(serveweb_async(val, tls, ctx), runtime.handle());
+ }
+ Err(err) => {
+ let msg = format!("Unable to bind web socket: {}", err);
+ return Err(std::io::Error::new(ErrorKind::Other, msg));
+ }
}
}
}
Ok(())
}
+// Load public certificate from file.
+fn load_certs(filename: &str) -> std::io::Result<Vec<pki_types::CertificateDer<'static>>> {
+ // Open certificate file.
+ let certfile = std::fs::File::open(filename)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("failed to open {}: {}", filename, e)))?;
+ let mut reader = std::io::BufReader::new(certfile);
+
+ // Load and return certificate.
+ rustls_pemfile::certs(&mut reader).collect()
+}
+
+// Load private key from file.
+fn load_private_key(filename: &str) -> std::io::Result<pki_types::PrivateKeyDer<'static>> {
+ // Open keyfile.
+ let keyfile = std::fs::File::open(filename)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("failed to open {}: {}", filename, e)))?;
+ let mut reader = std::io::BufReader::new(keyfile);
+
+ // Load and return a single private key.
+ rustls_pemfile::private_key(&mut reader).map(|key| key.unwrap())
+}
+
// impl below needed because the classes are used in the Context, which gets passed around.
unsafe impl Send for rustweb::CredentialsHolder {}
unsafe impl Sync for rustweb::CredentialsHolder {}
type ComboAddress;
}
+ pub struct IncomingTLS {
+ certificate: String,
+ key: String,
+ password: String,
+ }
+
+ struct IncomingWSConfig {
+ addresses: Vec<String>,
+ tls: IncomingTLS,
+ }
/*
* Functions callable from C++
*/
extern "Rust" {
// The main entry point, This function will return, but will setup thread(s) to handle requests.
- fn serveweb(addreses: &Vec<String>, urls: &[String], pwch: UniquePtr<CredentialsHolder>, apikeych: UniquePtr<CredentialsHolder>, acl: UniquePtr<NetmaskGroup>) -> Result<()>;
+ fn serveweb(incoming: &Vec<IncomingWSConfig>, urls: &[String], pwch: UniquePtr<CredentialsHolder>, apikeych: UniquePtr<CredentialsHolder>, acl: UniquePtr<NetmaskGroup>) -> Result<()>;
}
struct KeyValue {
''',
},
{
- 'name' : 'addresses',
+ 'name' : 'listen',
'section' : 'webservice',
- 'type' : LType.ListSocketAddresses,
- 'default' : '127.0.0.1:8082',
- 'help' : 'IP Addresses of webserver to listen on',
+ 'type' : LType.ListIncomingWSConfigs,
+ 'default' : '',
+ 'help' : 'XXXX',
'doc' : '''
-IP addresses for the webserver to listen on.
+XXXXX IP addresses for the webserver to listen on.
If this setting has a non-default value, :ref:`setting-yaml-webservice.address` :ref:`setting-yaml-webservice.port` and will be ignored.
''',
'skip-old': 'No equivalent old-style setting',
void serveRustWeb()
{
- ::rust::Vec<::rust::String> urls;
- for (const auto& [url, _] : g_urlmap) {
- urls.emplace_back(url);
- }
- auto address = ComboAddress(arg()["webserver-address"], arg().asNum("webserver-port"));
- ::rust::Vec<::rust::String> addressList{address.toStringWithPort()};
+ cerr << "SERVERUSTWEB" << endl;
+ ::rust::Vec<pdns::rust::web::rec::IncomingWSConfig> config;
if (g_yamlSettings) {
- auto addresses = g_yamlStruct.lock()->webservice.addresses;
- if (addresses.size() != 1 || addresses.at(0) != "127.0.0.1:8082") {
- addressList = std::move(addresses);
+ auto settings = g_yamlStruct.lock();
+ for (const auto& listen : settings->webservice.listen) {
+ pdns::rust::web::rec::IncomingWSConfig tmp;
+ for (const auto& address : listen.addresses) {
+ tmp.addresses.emplace_back(address);
+ }
+ tmp.tls = pdns::rust::web::rec::IncomingTLS{listen.tls.certificate, listen.tls.key, listen.tls.password};
+ config.emplace_back(tmp);
}
}
+ cerr << "Config ahs " << config.size() << " entries" << endl;
+ if (config.empty()) {
+ auto address = ComboAddress(arg()["webserver-address"], arg().asNum("webserver-port"));
+ pdns::rust::web::rec::IncomingWSConfig tmp{{::rust::String{address.toStringWithPort()}}, {}};
+ config.emplace_back(tmp);
+ }
+ ::rust::Vec<::rust::String> urls;
+ for (const auto& [url, _] : g_urlmap) {
+ urls.emplace_back(url);
+ }
auto passwordString = arg()["webserver-password"];
std::unique_ptr<CredentialsHolder> password;
if (!passwordString.empty()) {
acl.toMasks(::arg()["webserver-allow-from"]);
auto aclPtr = std::make_unique<pdns::rust::web::rec::NetmaskGroup>(acl);
- pdns::rust::web::rec::serveweb(addressList, ::rust::Slice<const ::rust::String>{urls.data(), urls.size()}, std::move(password), std::move(apikey), std::move(aclPtr));
+ cerr << "CALL SERVEWEB" << endl;
+ pdns::rust::web::rec::serveweb(config, ::rust::Slice<const ::rust::String>{urls.data(), urls.size()}, std::move(password), std::move(apikey), std::move(aclPtr));
}
static void fromCxxToRust(const HttpResponse& cxxresp, pdns::rust::web::rec::Response& rustResponse)