diff --git a/bin/src/ctl/mod.rs b/bin/src/ctl/mod.rs index 22a6c9ff6..148f9081f 100644 --- a/bin/src/ctl/mod.rs +++ b/bin/src/ctl/mod.rs @@ -47,8 +47,6 @@ pub enum CtlError { ArgsNeeded(String, String), #[error("could not load certificate")] LoadCertificate(CertificateError), - #[error("wrong address {0}: {1}")] - WrongAddress(String, UtilError), #[error("wrong input to create listener")] CreateListener(ConfigError), #[error("domain can not be empty")] @@ -161,19 +159,13 @@ impl CommandManager { key, address, tls_versions, - } => self.add_certificate( - address.to_string(), - &certificate, - &chain, - &key, - tls_versions, - ), + } => self.add_certificate(address.into(), &certificate, &chain, &key, tls_versions), CertificateCmd::Remove { certificate, address, fingerprint, } => self.remove_certificate( - address.to_string(), + address.into(), certificate.as_deref(), fingerprint.as_deref(), ), @@ -186,7 +178,7 @@ impl CommandManager { old_fingerprint, tls_versions, } => self.replace_certificate( - address.to_string(), + address.into(), &certificate, &chain, &key, diff --git a/bin/src/ctl/request_builder.rs b/bin/src/ctl/request_builder.rs index 6389ab625..1affeb0aa 100644 --- a/bin/src/ctl/request_builder.rs +++ b/bin/src/ctl/request_builder.rs @@ -11,7 +11,8 @@ use sozu_command_lib::{ LoadBalancingParams, MetricsConfiguration, PathRule, ProxyProtocolConfig, QueryCertificatesFilters, QueryClusterByDomain, QueryClustersHashes, RemoveBackend, RemoveCertificate, RemoveListener, ReplaceCertificate, RequestHttpFrontend, - RequestTcpFrontend, RulePosition, SoftStop, Status, SubscribeEvents, TlsVersion, + RequestTcpFrontend, RulePosition, SocketAddress, SoftStop, Status, SubscribeEvents, + TlsVersion, }, }; @@ -21,7 +22,6 @@ use crate::{ MetricsCmd, TcpFrontendCmd, TcpListenerCmd, }, ctl::CommandManager, - util::parse_socket_address, }; use super::CtlError; @@ -118,7 +118,7 @@ impl CommandManager { } => self.send_request( RequestType::AddBackend(AddBackend { cluster_id: id, - address: address.to_string(), + address: address.into(), backend_id, load_balancing_parameters: Some(LoadBalancingParams::default()), sticky_id, @@ -133,7 +133,7 @@ impl CommandManager { } => self.send_request( RequestType::RemoveBackend(RemoveBackend { cluster_id: id, - address: address.to_string(), + address: address.into(), backend_id, }) .into(), @@ -211,7 +211,7 @@ impl CommandManager { TcpFrontendCmd::Add { id, address, tags } => self.send_request( RequestType::AddTcpFrontend(RequestTcpFrontend { cluster_id: id, - address: address.to_string(), + address: address.into(), tags: tags.unwrap_or(BTreeMap::new()), }) .into(), @@ -219,7 +219,7 @@ impl CommandManager { TcpFrontendCmd::Remove { id, address } => self.send_request( RequestType::RemoveTcpFrontend(RequestTcpFrontend { cluster_id: id, - address: address.to_string(), + address: address.into(), ..Default::default() }) .into(), @@ -241,7 +241,7 @@ impl CommandManager { } => self.send_request( RequestType::AddHttpFrontend(RequestHttpFrontend { cluster_id: route.into(), - address: address.to_string(), + address: address.into(), hostname, path: PathRule::from_cli_options(path_prefix, path_regex, path_equals), method: method.map(String::from), @@ -264,7 +264,7 @@ impl CommandManager { } => self.send_request( RequestType::RemoveHttpFrontend(RequestHttpFrontend { cluster_id: route.into(), - address: address.to_string(), + address: address.into(), hostname, path: PathRule::from_cli_options(path_prefix, path_regex, path_equals), method: method.map(String::from), @@ -289,7 +289,7 @@ impl CommandManager { } => self.send_request( RequestType::AddHttpsFrontend(RequestHttpFrontend { cluster_id: route.into(), - address: address.to_string(), + address: address.into(), hostname, path: PathRule::from_cli_options(path_prefix, path_regex, path_equals), method: method.map(String::from), @@ -312,7 +312,7 @@ impl CommandManager { } => self.send_request( RequestType::RemoveHttpsFrontend(RequestHttpFrontend { cluster_id: route.into(), - address: address.to_string(), + address: address.into(), hostname, path: PathRule::from_cli_options(path_prefix, path_regex, path_equals), method: method.map(String::from), @@ -339,7 +339,7 @@ impl CommandManager { request_timeout, connect_timeout, } => { - let https_listener = ListenerBuilder::new_https(address) + let https_listener = ListenerBuilder::new_https(address.into()) .with_public_address(public_address) .with_answer_404_path(answer_404) .with_answer_503_path(answer_503) @@ -357,13 +357,13 @@ impl CommandManager { self.send_request(RequestType::AddHttpsListener(https_listener).into()) } HttpsListenerCmd::Remove { address } => { - self.remove_listener(address.to_string(), ListenerType::Https) + self.remove_listener(address.into(), ListenerType::Https) } HttpsListenerCmd::Activate { address } => { - self.activate_listener(address.to_string(), ListenerType::Https) + self.activate_listener(address.into(), ListenerType::Https) } HttpsListenerCmd::Deactivate { address } => { - self.deactivate_listener(address.to_string(), ListenerType::Https) + self.deactivate_listener(address.into(), ListenerType::Https) } } } @@ -382,7 +382,7 @@ impl CommandManager { request_timeout, connect_timeout, } => { - let http_listener = ListenerBuilder::new_http(address) + let http_listener = ListenerBuilder::new_http(address.into()) .with_public_address(public_address) .with_answer_404_path(answer_404) .with_answer_503_path(answer_503) @@ -398,13 +398,13 @@ impl CommandManager { self.send_request(RequestType::AddHttpListener(http_listener).into()) } HttpListenerCmd::Remove { address } => { - self.remove_listener(address.to_string(), ListenerType::Http) + self.remove_listener(address.into(), ListenerType::Http) } HttpListenerCmd::Activate { address } => { - self.activate_listener(address.to_string(), ListenerType::Http) + self.activate_listener(address.into(), ListenerType::Http) } HttpListenerCmd::Deactivate { address } => { - self.deactivate_listener(address.to_string(), ListenerType::Http) + self.deactivate_listener(address.into(), ListenerType::Http) } } } @@ -416,7 +416,7 @@ impl CommandManager { public_address, expect_proxy, } => { - let listener = ListenerBuilder::new_tcp(address) + let listener = ListenerBuilder::new_tcp(address.into()) .with_public_address(public_address) .with_expect_proxy(expect_proxy) .to_tcp(Some(&self.config)) @@ -425,13 +425,13 @@ impl CommandManager { self.send_request(RequestType::AddTcpListener(listener).into()) } TcpListenerCmd::Remove { address } => { - self.remove_listener(address.to_string(), ListenerType::Tcp) + self.remove_listener(address.into(), ListenerType::Tcp) } TcpListenerCmd::Activate { address } => { - self.activate_listener(address.to_string(), ListenerType::Tcp) + self.activate_listener(address.into(), ListenerType::Tcp) } TcpListenerCmd::Deactivate { address } => { - self.deactivate_listener(address.to_string(), ListenerType::Tcp) + self.deactivate_listener(address.into(), ListenerType::Tcp) } } } @@ -442,15 +442,12 @@ impl CommandManager { pub fn remove_listener( &mut self, - address: String, + address: SocketAddress, listener_type: ListenerType, ) -> Result<(), CtlError> { - let address = parse_socket_address(&address) - .map_err(|util_err| CtlError::WrongAddress(address, util_err))?; - self.send_request( RequestType::RemoveListener(RemoveListener { - address: address.to_string(), + address, proxy: listener_type.into(), }) .into(), @@ -459,15 +456,12 @@ impl CommandManager { pub fn activate_listener( &mut self, - address: String, + address: SocketAddress, listener_type: ListenerType, ) -> Result<(), CtlError> { - let address = parse_socket_address(&address) - .map_err(|util_err| CtlError::WrongAddress(address, util_err))?; - self.send_request( RequestType::ActivateListener(ActivateListener { - address: address.to_string(), + address, proxy: listener_type.into(), from_scm: false, }) @@ -477,15 +471,12 @@ impl CommandManager { pub fn deactivate_listener( &mut self, - address: String, + address: SocketAddress, listener_type: ListenerType, ) -> Result<(), CtlError> { - let address = parse_socket_address(&address) - .map_err(|util_err| CtlError::WrongAddress(address, util_err))?; - self.send_request( RequestType::DeactivateListener(DeactivateListener { - address: address.to_string(), + address, proxy: listener_type.into(), to_scm: false, }) @@ -499,7 +490,7 @@ impl CommandManager { pub fn add_certificate( &mut self, - address: String, + address: SocketAddress, certificate_path: &str, certificate_chain_path: &str, key_path: &str, @@ -527,7 +518,7 @@ impl CommandManager { #[allow(clippy::too_many_arguments)] pub fn replace_certificate( &mut self, - address: String, + address: SocketAddress, new_certificate_path: &str, new_certificate_chain_path: &str, new_key_path: &str, @@ -575,7 +566,7 @@ impl CommandManager { pub fn remove_certificate( &mut self, - address: String, + address: SocketAddress, certificate_path: Option<&str>, fingerprint: Option<&str>, ) -> Result<(), CtlError> { diff --git a/bin/src/util.rs b/bin/src/util.rs index 5f1c09ab3..b888bd970 100644 --- a/bin/src/util.rs +++ b/bin/src/util.rs @@ -2,7 +2,6 @@ use std::{ ffi::OsString, fs::{read_link, File}, io::{Error as IoError, Write}, - net::{AddrParseError, SocketAddr}, os::unix::io::RawFd, path::PathBuf, }; @@ -45,8 +44,6 @@ pub enum UtilError { or use the SOZU_CONFIG environment variable when building sozu." )] GetConfigFilePath, - #[error("could not parse socket address: {0}")] - ParseSocketAddress(AddrParseError), } /// FD_CLOEXEC is set by default on every fd in Rust standard lib, @@ -117,12 +114,6 @@ pub fn get_config_file_path(args: &cli::Args) -> Result<&str, UtilError> { } } -pub fn parse_socket_address(address: &str) -> Result { - address - .parse::() - .map_err(UtilError::ParseSocketAddress) -} - #[cfg(target_os = "freebsd")] pub unsafe fn get_executable_path() -> Result { let mut capacity = PATH_MAX as usize; diff --git a/command/src/command.proto b/command/src/command.proto index 391f67449..e7c92547a 100644 --- a/command/src/command.proto +++ b/command/src/command.proto @@ -115,8 +115,8 @@ message CountRequests {} // details of an HTTP listener message HttpListenerConfig { - required string address = 1; - optional string public_address = 2; + required SocketAddress address = 1; + optional SocketAddress public_address = 2; required string answer_404 = 3; required string answer_503 = 4; required bool expect_proxy = 5 [default = false]; @@ -135,8 +135,8 @@ message HttpListenerConfig { // details of an HTTPS listener message HttpsListenerConfig { - required string address = 1; - optional string public_address = 2; + required SocketAddress address = 1; + optional SocketAddress public_address = 2; required string answer_404 = 3; required string answer_503 = 4; required bool expect_proxy = 5 [default = false]; @@ -168,8 +168,8 @@ message HttpsListenerConfig { // details of an TCP listener message TcpListenerConfig { - required string address = 1; - optional string public_address = 2; + required SocketAddress address = 1; + optional SocketAddress public_address = 2; required bool expect_proxy = 3 [default = false]; // client inactive time, in seconds required uint32 front_timeout = 4 [default = 60]; @@ -182,19 +182,19 @@ message TcpListenerConfig { } message ActivateListener { - required string address = 1; + required SocketAddress address = 1; required ListenerType proxy = 2; required bool from_scm = 3; } message DeactivateListener { - required string address = 1; + required SocketAddress address = 1; required ListenerType proxy = 2; required bool to_scm = 3; } message RemoveListener { - required string address = 1; + required SocketAddress address = 1; required ListenerType proxy = 2; } @@ -217,7 +217,7 @@ message ListenersList { // An HTTP or HTTPS frontend, as order to, or received from, Sōzu message RequestHttpFrontend { optional string cluster_id = 1; - required string address = 2; + required SocketAddress address = 2; required string hostname = 3; required PathRule path = 4; optional string method = 5; @@ -229,7 +229,7 @@ message RequestHttpFrontend { message RequestTcpFrontend { required string cluster_id = 1; // the socket address on which to listen for incoming traffic - required string address = 2; + required SocketAddress address = 2; // custom tags to identify the frontend in the access logs map tags = 3; } @@ -269,20 +269,20 @@ enum RulePosition { // Add a new TLS certificate to an HTTPs listener message AddCertificate { - required string address = 1; + required SocketAddress address = 1; required CertificateAndKey certificate = 2; // A unix timestamp. Overrides certificate expiration. optional int64 expired_at = 3; } message RemoveCertificate { - required string address = 1; + required SocketAddress address = 1; // a hex-encoded TLS fingerprint to identify the certificate to remove required string fingerprint = 2; } message ReplaceCertificate { - required string address = 1; + required SocketAddress address = 1; required CertificateAndKey new_certificate = 2; // a hex-encoded TLS fingerprint to identify the old certificate required string old_fingerprint = 3; @@ -323,7 +323,7 @@ message ListOfCertificatesByAddress { // Summaries of certificates for a given address message CertificatesByAddress { - required string address = 1; + required SocketAddress address = 1; repeated CertificateSummary certificate_summaries = 2; } @@ -382,7 +382,7 @@ message AddBackend { required string cluster_id = 1; required string backend_id = 2; // the socket address of the backend - required string address = 3; + required SocketAddress address = 3; optional string sticky_id = 4; optional LoadBalancingParams load_balancing_parameters = 5; optional bool backup = 6; @@ -393,7 +393,7 @@ message RemoveBackend { required string cluster_id = 1; required string backend_id = 2; // the socket address of the backend - required string address = 3 ; + required SocketAddress address = 3 ; } message LoadBalancingParams { @@ -502,7 +502,7 @@ message Event { required EventKind kind = 1; optional string cluster_id = 2; optional string backend_id = 3; - optional string address = 4; + optional SocketAddress address = 4; } enum EventKind { @@ -607,4 +607,28 @@ message Percentiles { message RequestCounts { map map = 1; +} + +// matches std::net::SocketAddr in the Rust library +// beware that the ports are expressed with uint32 here, +// but they should NOT exceed uint16 value +message SocketAddress { + required IpAddress ip = 1; + required uint32 port = 2; +} + +message IpAddress { + oneof inner { + uint32 v4 = 1; + Uint128 v6 = 2; + } +} + +// used to represent the 128 bits of an IPv6 address +message Uint128 { + // higher value, first 8 bytes of the ip + required uint64 low = 1; + // lower value, last 8 bytes of the ip + required uint64 high = 2; + } \ No newline at end of file diff --git a/command/src/config.rs b/command/src/config.rs index efe1cdc26..594634021 100644 --- a/command/src/config.rs +++ b/command/src/config.rs @@ -65,8 +65,8 @@ use crate::{ request::RequestType, ActivateListener, AddBackend, AddCertificate, CertificateAndKey, Cluster, HttpListenerConfig, HttpsListenerConfig, ListenerType, LoadBalancingAlgorithms, LoadBalancingParams, LoadMetric, MetricsConfiguration, PathRule, ProxyProtocolConfig, - Request, RequestHttpFrontend, RequestTcpFrontend, RulePosition, TcpListenerConfig, - TlsVersion, + Request, RequestHttpFrontend, RequestTcpFrontend, RulePosition, SocketAddress, + TcpListenerConfig, TlsVersion, }, request::WorkerRequest, ObjectKind, @@ -185,8 +185,6 @@ pub enum MissingKind { #[derive(thiserror::Error, Debug)] pub enum ConfigError { - #[error("Could not parse socket address {address}: {error}")] - ParseSocketAddress { address: String, error: String }, #[error("env path not found: {0}")] Env(String), #[error("Could not open file {path_to_open}: {io_error}")] @@ -209,8 +207,8 @@ pub enum ConfigError { InvalidFrontendConfig(String), #[error("invalid path {0:?}")] InvalidPath(PathBuf), - #[error("listening address {0} is already used in the configuration")] - ListenerAddressAlreadyInUse(String), + #[error("listening address {0:?} is already used in the configuration")] + ListenerAddressAlreadyInUse(SocketAddr), #[error("missing {0:?}")] Missing(MissingKind), #[error("could not get parent directory for file {0}")] @@ -231,12 +229,12 @@ pub enum ConfigError { } /// An HTTP, HTTPS or TCP listener as parsed from the `Listeners` section in the toml -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct ListenerBuilder { - pub address: String, + pub address: SocketAddr, pub protocol: Option, - pub public_address: Option, + pub public_address: Option, /// path to the 404 html file pub answer_404: Option, /// path to the 503 html file @@ -273,50 +271,50 @@ pub fn default_sticky_name() -> String { impl ListenerBuilder { /// starts building an HTTP Listener with config values for timeouts, /// or defaults if no config is provided - pub fn new_http(address: S) -> ListenerBuilder - where - S: ToString, - { + pub fn new_http(address: SocketAddress) -> ListenerBuilder { Self::new(address, ListenerProtocol::Http) } /// starts building an HTTPS Listener with config values for timeouts, /// or defaults if no config is provided - pub fn new_tcp(address: S) -> ListenerBuilder - where - S: ToString, - { + pub fn new_tcp(address: SocketAddress) -> ListenerBuilder { Self::new(address, ListenerProtocol::Tcp) } /// starts building a TCP Listener with config values for timeouts, /// or defaults if no config is provided - pub fn new_https(address: S) -> ListenerBuilder - where - S: ToString, - { + pub fn new_https(address: SocketAddress) -> ListenerBuilder { Self::new(address, ListenerProtocol::Https) } /// starts building a Listener - fn new(address: S, protocol: ListenerProtocol) -> ListenerBuilder - where - S: ToString, - { + fn new(address: SocketAddress, protocol: ListenerProtocol) -> ListenerBuilder { ListenerBuilder { - address: address.to_string(), + address: address.into(), protocol: Some(protocol), sticky_name: DEFAULT_STICKY_NAME.to_string(), - ..Default::default() + public_address: None, + answer_404: None, + answer_503: None, + tls_versions: None, + cipher_list: None, + cipher_suites: None, + expect_proxy: None, + certificate: None, + certificate_chain: None, + key: None, + front_timeout: None, + back_timeout: None, + connect_timeout: None, + request_timeout: None, + config: None, + send_tls13_tickets: None, } } - pub fn with_public_address(&mut self, public_address: Option) -> &mut Self - where - S: ToString, - { + pub fn with_public_address(&mut self, public_address: Option) -> &mut Self { if let Some(address) = public_address { - self.public_address = Some(address.to_string()); + self.public_address = Some(address); } self } @@ -412,17 +410,6 @@ impl ListenerBuilder { self } - pub fn parse_address(&self) -> Result { - parse_socket_address(&self.address) - } - - pub fn parse_public_address(&self) -> Result, ConfigError> { - match &self.public_address { - Some(a) => Ok(Some(parse_socket_address(a)?)), - None => Ok(None), - } - } - /// Assign the timeouts of the config to this listener, only if timeouts did not exist fn assign_config_timeouts(&mut self, config: &Config) { self.front_timeout = Some(self.front_timeout.unwrap_or(config.front_timeout)); @@ -446,13 +433,9 @@ impl ListenerBuilder { let (answer_404, answer_503) = self.get_404_503_answers()?; - let _address = self.parse_address()?; - - let _public_address = self.parse_public_address()?; - let configuration = HttpListenerConfig { - address: self.address.clone(), - public_address: self.public_address.clone(), + address: self.address.into(), + public_address: self.public_address.map(|a| a.into()), expect_proxy: self.expect_proxy.unwrap_or(false), sticky_name: self.sticky_name.clone(), front_timeout: self.front_timeout.unwrap_or(DEFAULT_FRONT_TIMEOUT), @@ -532,23 +515,16 @@ impl ListenerBuilder { .map(split_certificate_chain) .unwrap_or_else(Vec::new); - let (answer_404, answer_503) = self - .get_404_503_answers() - //.with_context(|| "Could not get 404 and 503 answers from file system") - ?; - - let _address = self.parse_address()?; - - let _public_address = self.parse_public_address()?; + let (answer_404, answer_503) = self.get_404_503_answers()?; if let Some(config) = config { self.assign_config_timeouts(config); } let https_listener_config = HttpsListenerConfig { - address: self.address.clone(), + address: self.address.into(), sticky_name: self.sticky_name.clone(), - public_address: self.public_address.clone(), + public_address: self.public_address.map(|a| a.into()), cipher_list, versions, expect_proxy: self.expect_proxy.unwrap_or(false), @@ -582,17 +558,13 @@ impl ListenerBuilder { }); } - let _address = self.parse_address()?; - - let _public_address = self.parse_public_address()?; - if let Some(config) = config { self.assign_config_timeouts(config); } Ok(TcpListenerConfig { - address: self.address.clone(), - public_address: self.public_address.clone(), + address: self.address.into(), + public_address: self.public_address.map(|a| a.into()), expect_proxy: self.expect_proxy.unwrap_or(false), front_timeout: self.front_timeout.unwrap_or(DEFAULT_FRONT_TIMEOUT), back_timeout: self.back_timeout.unwrap_or(DEFAULT_BACK_TIMEOUT), @@ -617,15 +589,6 @@ impl ListenerBuilder { } } -fn parse_socket_address(address: &str) -> Result { - address - .parse::() - .map_err(|parse_error| ConfigError::ParseSocketAddress { - error: parse_error.to_string(), - address: address.to_owned(), - }) -} - fn open_and_read_file(path: &str) -> Result { let mut content = String::new(); let mut file = File::open(path).map_err(|io_error| ConfigError::FileOpen { @@ -928,7 +891,7 @@ impl HttpFrontendConfig { if self.key.is_some() && self.certificate.is_some() { v.push( RequestType::AddCertificate(AddCertificate { - address: self.address.to_string(), + address: self.address.into(), certificate: CertificateAndKey { key: self.key.clone().unwrap(), certificate: self.certificate.clone().unwrap(), @@ -944,7 +907,7 @@ impl HttpFrontendConfig { v.push( RequestType::AddHttpsFrontend(RequestHttpFrontend { cluster_id: Some(cluster_id.to_string()), - address: self.address.to_string(), + address: self.address.into(), hostname: self.hostname.clone(), path: self.path.clone(), method: self.method.clone(), @@ -958,7 +921,7 @@ impl HttpFrontendConfig { v.push( RequestType::AddHttpFrontend(RequestHttpFrontend { cluster_id: Some(cluster_id.to_string()), - address: self.address.to_string(), + address: self.address.into(), hostname: self.hostname.clone(), path: self.path.clone(), method: self.method.clone(), @@ -1015,7 +978,7 @@ impl HttpClusterConfig { backend_id: backend.backend_id.clone().unwrap_or_else(|| { format!("{}-{}-{}", self.cluster_id, backend_count, backend.address) }), - address: backend.address.to_string(), + address: backend.address.into(), load_balancing_parameters, sticky_id: backend.sticky_id.clone(), backup: backend.backup, @@ -1062,7 +1025,7 @@ impl TcpClusterConfig { v.push( RequestType::AddTcpFrontend(RequestTcpFrontend { cluster_id: self.cluster_id.clone(), - address: frontend.address.to_string(), + address: frontend.address.into(), tags: frontend.tags.clone().unwrap_or(BTreeMap::new()), }) .into(), @@ -1080,7 +1043,7 @@ impl TcpClusterConfig { backend_id: backend.backend_id.clone().unwrap_or_else(|| { format!("{}-{}-{}", self.cluster_id, backend_count, backend.address) }), - address: backend.address.to_string(), + address: backend.address.into(), load_balancing_parameters, sticky_id: backend.sticky_id.clone(), backup: backend.backup, @@ -1167,12 +1130,10 @@ impl FileConfig { if let Some(listeners) = config.listeners.as_ref() { for listener in listeners.iter() { - if reserved_address.contains(&listener.parse_address()?) { - return Err(ConfigError::ListenerAddressAlreadyInUse( - listener.address.to_string(), - )); + if reserved_address.contains(&listener.address) { + return Err(ConfigError::ListenerAddressAlreadyInUse(listener.address)); } - reserved_address.insert(listener.parse_address()?); + reserved_address.insert(listener.address); } } @@ -1305,26 +1266,23 @@ impl ConfigBuilder { fn populate_listeners(&mut self, listeners: Vec) -> Result<(), ConfigError> { for listener in listeners.iter() { - let address = listener.parse_address()?; - if self.known_addresses.contains_key(&address) { - return Err(ConfigError::ListenerAddressAlreadyInUse( - listener.address.to_string(), - )); + if self.known_addresses.contains_key(&listener.address) { + return Err(ConfigError::ListenerAddressAlreadyInUse(listener.address)); } let protocol = listener .protocol .ok_or(ConfigError::Missing(MissingKind::Protocol))?; - self.known_addresses.insert(address, protocol); + self.known_addresses.insert(listener.address, protocol); if listener.expect_proxy == Some(true) { - self.expect_proxy_addresses.insert(address); + self.expect_proxy_addresses.insert(listener.address); } if listener.public_address.is_some() && listener.expect_proxy == Some(true) { return Err(ConfigError::Incompatible { object: ObjectKind::Listener, - id: listener.address.to_owned(), + id: listener.address.to_string(), kind: IncompatibilityKind::PublicAddress, }); } @@ -1345,7 +1303,6 @@ impl ConfigBuilder { for (id, file_cluster_config) in file_cluster_configs.drain() { let mut cluster_config = file_cluster_config.to_cluster_config(id.as_str(), &self.expect_proxy_addresses)?; - // .with_context(|| format!("error parsing cluster configuration for cluster {id}"))?; match cluster_config { ClusterConfig::Http(ref mut http) => { @@ -1367,7 +1324,7 @@ impl ConfigBuilder { if frontend.certificate.is_none() { if let Some(https_listener) = self.built.https_listeners.iter().find(|listener| { - listener.address == frontend.address.to_string() + listener.address == frontend.address.into() && listener.certificate.is_some() }) { @@ -1390,14 +1347,14 @@ impl ConfigBuilder { // create a default listener for that front let file_listener_protocol = if frontend.certificate.is_some() { self.push_tls_listener(ListenerBuilder::new( - frontend.address.to_string(), + frontend.address.into(), ListenerProtocol::Https, ))?; ListenerProtocol::Https } else { self.push_http_listener(ListenerBuilder::new( - frontend.address.to_string(), + frontend.address.into(), ListenerProtocol::Http, ))?; @@ -1422,7 +1379,7 @@ impl ConfigBuilder { None => { // create a default listener for that front self.push_tcp_listener(ListenerBuilder::new( - frontend.address.to_string(), + frontend.address.into(), ListenerProtocol::Tcp, ))?; self.known_addresses @@ -1794,14 +1751,20 @@ mod tests { #[test] fn serialize() { - let http = ListenerBuilder::new("127.0.0.1:8080", ListenerProtocol::Http) - .with_answer_404_path(Some("404.html")) - .to_owned(); + let http = ListenerBuilder::new( + SocketAddress::new_v4(127, 0, 0, 1, 8080), + ListenerProtocol::Http, + ) + .with_answer_404_path(Some("404.html")) + .to_owned(); println!("http: {:?}", to_string(&http)); - let https = ListenerBuilder::new("127.0.0.1:8443", ListenerProtocol::Https) - .with_answer_404_path(Some("404.html")) - .to_owned(); + let https = ListenerBuilder::new( + SocketAddress::new_v4(127, 0, 0, 1, 8443), + ListenerProtocol::Https, + ) + .with_answer_404_path(Some("404.html")) + .to_owned(); println!("https: {:?}", to_string(&https)); let listeners = vec![http, https]; diff --git a/command/src/proto/display.rs b/command/src/proto/display.rs index 4bc8df774..b123a0437 100644 --- a/command/src/proto/display.rs +++ b/command/src/proto/display.rs @@ -1,6 +1,7 @@ use std::{ collections::{BTreeMap, HashMap, HashSet}, fmt::{Display, Formatter}, + net::SocketAddr, }; use prettytable::{cell, row, Row, Table}; @@ -18,6 +19,8 @@ use crate::proto::{ DisplayError, }; +use super::command::SocketAddress; + impl Display for CertificateAndKey { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let versions = self.versions.iter().fold(String::new(), |acc, tls_v| { @@ -940,3 +943,9 @@ fn create_cluster_table(headers: Vec<&str>, data: &BTreeMap) -> std::fmt::Result { + write!(f, "{}", SocketAddr::from(self.clone())) + } +} diff --git a/command/src/request.rs b/command/src/request.rs index 459cc1abc..234d41f50 100644 --- a/command/src/request.rs +++ b/command/src/request.rs @@ -3,7 +3,7 @@ use std::{ fmt::{self, Display}, fs::File, io::Read, - net::SocketAddr, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, str::FromStr, }; @@ -14,8 +14,8 @@ use crate::{ parser::parse_several_requests, proto::{ command::{ - request::RequestType, LoadBalancingAlgorithms, PathRuleKind, Request, - RequestHttpFrontend, RulePosition, + ip_address, request::RequestType, IpAddress, LoadBalancingAlgorithms, PathRuleKind, + Request, RequestHttpFrontend, RulePosition, SocketAddress, Uint128, }, display::format_request_type, }, @@ -24,8 +24,6 @@ use crate::{ #[derive(thiserror::Error, Debug)] pub enum RequestError { - #[error("Invalid address {address}: {error}")] - InvalidSocketAddress { address: String, error: String }, #[error("invalid value {value} for field '{name}'")] InvalidValue { name: String, value: i32 }, #[error("Could not read requests from file: {0}")] @@ -201,12 +199,7 @@ impl RequestHttpFrontend { /// convert a requested frontend to a usable one by parsing its address pub fn to_frontend(self) -> Result { Ok(HttpFrontend { - address: self.address.parse::().map_err(|parse_error| { - RequestError::InvalidSocketAddress { - address: self.address.clone(), - error: parse_error.to_string(), - } - })?, + address: self.address.into(), cluster_id: self.cluster_id, hostname: self.hostname, path: self.path, @@ -277,3 +270,57 @@ impl FromStr for LoadBalancingAlgorithms { } } } + +impl SocketAddress { + pub fn new_v4(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self { + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(a, b, c, d)), port).into() + } +} + +impl From for SocketAddress { + fn from(socket_addr: SocketAddr) -> SocketAddress { + let ip_inner = match socket_addr { + SocketAddr::V4(ip_v4_addr) => ip_address::Inner::V4(u32::from(*ip_v4_addr.ip())), + SocketAddr::V6(ip_v6_addr) => { + ip_address::Inner::V6(Uint128::from(u128::from(*ip_v6_addr.ip()))) + } + }; + + SocketAddress { + port: socket_addr.port() as u32, + ip: IpAddress { + inner: Some(ip_inner), + }, + } + } +} + +impl From for SocketAddr { + fn from(socket_address: SocketAddress) -> Self { + let port = socket_address.port as u16; + + let ip = match socket_address.ip.inner { + Some(inner) => match inner { + ip_address::Inner::V4(v4_value) => IpAddr::V4(Ipv4Addr::from(v4_value)), + ip_address::Inner::V6(v6_value) => IpAddr::V6(Ipv6Addr::from(u128::from(v6_value))), + }, + None => IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), // should never happen + }; + + SocketAddr::new(ip, port) + } +} + +impl From for u128 { + fn from(value: Uint128) -> Self { + value.low as u128 | ((value.high as u128) << 64) + } +} + +impl From for Uint128 { + fn from(value: u128) -> Self { + let low = value as u64; + let high = (value >> 64) as u64; + Uint128 { low, high } + } +} diff --git a/command/src/response.rs b/command/src/response.rs index c60d3e0f7..99b534157 100644 --- a/command/src/response.rs +++ b/command/src/response.rs @@ -49,7 +49,7 @@ impl From for RequestHttpFrontend { }; RequestHttpFrontend { cluster_id: val.cluster_id, - address: val.address.to_string(), + address: val.address.into(), hostname: val.hostname, path: val.path, method: val.method, @@ -64,7 +64,7 @@ impl From for AddBackend { AddBackend { cluster_id: val.cluster_id, backend_id: val.backend_id, - address: val.address.to_string(), + address: val.address.into(), sticky_id: val.sticky_id, load_balancing_parameters: val.load_balancing_parameters, backup: val.backup, @@ -154,7 +154,7 @@ impl From for RequestTcpFrontend { fn from(val: TcpFrontend) -> Self { RequestTcpFrontend { cluster_id: val.cluster_id, - address: val.address.to_string(), + address: val.address.into(), tags: val.tags, } } @@ -202,7 +202,7 @@ impl Backend { pub fn to_add_backend(self) -> AddBackend { AddBackend { cluster_id: self.cluster_id, - address: self.address.to_string(), + address: self.address.into(), sticky_id: self.sticky_id, backend_id: self.backend_id, load_balancing_parameters: self.load_balancing_parameters, diff --git a/command/src/state.rs b/command/src/state.rs index 9532f34b2..9883b25d0 100644 --- a/command/src/state.rs +++ b/command/src/state.rs @@ -21,7 +21,7 @@ use crate::{ HttpsListenerConfig, ListedFrontends, ListenerType, ListenersList, PathRule, QueryCertificatesFilters, RemoveBackend, RemoveCertificate, RemoveListener, ReplaceCertificate, Request, RequestCounts, RequestHttpFrontend, RequestTcpFrontend, - TcpListenerConfig, + SocketAddress, TcpListenerConfig, }, display::format_request_type, }, @@ -53,8 +53,6 @@ pub enum StateError { RemoveCertificate(String), #[error("Could not replace certificate: {0}")] ReplaceCertificate(String), - #[error("The provided socket address '{address}' is wrong: {error}")] - WrongSocketAddress { address: String, error: String }, #[error( "Could not convert the frontend to an insertable one. Frontend: {frontend} error: {error}" )] @@ -82,11 +80,11 @@ pub struct ConfigState { pub clusters: BTreeMap, pub backends: BTreeMap>, /// socket address -> HTTP listener - pub http_listeners: BTreeMap, + pub http_listeners: BTreeMap, /// socket address -> HTTPS listener - pub https_listeners: BTreeMap, + pub https_listeners: BTreeMap, /// socket address -> TCP listener - pub tcp_listeners: BTreeMap, + pub tcp_listeners: BTreeMap, /// HTTP frontends, indexed by a summary of each front's address;hostname;path, for uniqueness. /// For example: `"0.0.0.0:8080;lolcatho.st;P/api"` pub http_fronts: BTreeMap, @@ -184,13 +182,13 @@ impl ConfigState { } fn add_http_listener(&mut self, listener: &HttpListenerConfig) -> Result<(), StateError> { - let address = listener.address.to_string(); - match self.http_listeners.entry(address.clone()) { + let address: SocketAddr = listener.address.clone().into(); + match self.http_listeners.entry(address) { BTreeMapEntry::Vacant(vacant_entry) => vacant_entry.insert(listener.clone()), BTreeMapEntry::Occupied(_) => { return Err(StateError::Exists { kind: ObjectKind::HttpListener, - id: address, + id: address.to_string(), }) } }; @@ -198,13 +196,13 @@ impl ConfigState { } fn add_https_listener(&mut self, listener: &HttpsListenerConfig) -> Result<(), StateError> { - let address = listener.address.to_string(); - match self.https_listeners.entry(address.clone()) { + let address: SocketAddr = listener.address.clone().into(); + match self.https_listeners.entry(address) { BTreeMapEntry::Vacant(vacant_entry) => vacant_entry.insert(listener.clone()), BTreeMapEntry::Occupied(_) => { return Err(StateError::Exists { kind: ObjectKind::HttpsListener, - id: address, + id: address.to_string(), }) } }; @@ -212,13 +210,13 @@ impl ConfigState { } fn add_tcp_listener(&mut self, listener: &TcpListenerConfig) -> Result<(), StateError> { - let address = listener.address.to_string(); - match self.tcp_listeners.entry(address.clone()) { + let address: SocketAddr = listener.address.clone().into(); + match self.tcp_listeners.entry(address) { BTreeMapEntry::Vacant(vacant_entry) => vacant_entry.insert(listener.clone()), BTreeMapEntry::Occupied(_) => { return Err(StateError::Exists { kind: ObjectKind::TcpListener, - id: address, + id: address.to_string(), }) } }; @@ -227,27 +225,27 @@ impl ConfigState { fn remove_listener(&mut self, remove: &RemoveListener) -> Result<(), StateError> { match ListenerType::try_from(remove.proxy)? { - ListenerType::Http => self.remove_http_listener(&remove.address), - ListenerType::Https => self.remove_https_listener(&remove.address), - ListenerType::Tcp => self.remove_tcp_listener(&remove.address), + ListenerType::Http => self.remove_http_listener(&remove.address.clone().into()), + ListenerType::Https => self.remove_https_listener(&remove.address.clone().into()), + ListenerType::Tcp => self.remove_tcp_listener(&remove.address.clone().into()), } } - fn remove_http_listener(&mut self, address: &str) -> Result<(), StateError> { + fn remove_http_listener(&mut self, address: &SocketAddr) -> Result<(), StateError> { if self.http_listeners.remove(address).is_none() { return Err(StateError::NoChange); } Ok(()) } - fn remove_https_listener(&mut self, address: &str) -> Result<(), StateError> { + fn remove_https_listener(&mut self, address: &SocketAddr) -> Result<(), StateError> { if self.https_listeners.remove(address).is_none() { return Err(StateError::NoChange); } Ok(()) } - fn remove_tcp_listener(&mut self, address: &str) -> Result<(), StateError> { + fn remove_tcp_listener(&mut self, address: &SocketAddr) -> Result<(), StateError> { if self.tcp_listeners.remove(address).is_none() { return Err(StateError::NoChange); } @@ -258,27 +256,27 @@ impl ConfigState { match ListenerType::try_from(activate.proxy)? { ListenerType::Http => self .http_listeners - .get_mut(&activate.address) + .get_mut(&activate.address.clone().into()) .map(|listener| listener.active = true) .ok_or(StateError::NotFound { kind: ObjectKind::HttpListener, - id: activate.address.to_owned(), + id: activate.address.to_string(), }), ListenerType::Https => self .https_listeners - .get_mut(&activate.address) + .get_mut(&activate.address.clone().into()) .map(|listener| listener.active = true) .ok_or(StateError::NotFound { kind: ObjectKind::HttpsListener, - id: activate.address.to_owned(), + id: activate.address.to_string(), }), ListenerType::Tcp => self .tcp_listeners - .get_mut(&activate.address) + .get_mut(&activate.address.clone().into()) .map(|listener| listener.active = true) .ok_or(StateError::NotFound { kind: ObjectKind::TcpListener, - id: activate.address.to_owned(), + id: activate.address.to_string(), }), } } @@ -287,27 +285,27 @@ impl ConfigState { match ListenerType::try_from(deactivate.proxy)? { ListenerType::Http => self .http_listeners - .get_mut(&deactivate.address) + .get_mut(&deactivate.address.clone().into()) .map(|listener| listener.active = false) .ok_or(StateError::NotFound { kind: ObjectKind::HttpListener, - id: deactivate.address.to_owned(), + id: deactivate.address.to_string(), }), ListenerType::Https => self .https_listeners - .get_mut(&deactivate.address) + .get_mut(&deactivate.address.clone().into()) .map(|listener| listener.active = false) .ok_or(StateError::NotFound { kind: ObjectKind::HttpsListener, - id: deactivate.address.to_owned(), + id: deactivate.address.to_string(), }), ListenerType::Tcp => self .tcp_listeners - .get_mut(&deactivate.address) + .get_mut(&deactivate.address.clone().into()) .map(|listener| listener.active = false) .ok_or(StateError::NotFound { kind: ObjectKind::TcpListener, - id: deactivate.address.to_owned(), + id: deactivate.address.to_string(), }), } } @@ -383,11 +381,9 @@ impl ConfigState { )?, ); - let address = parse_socket_address(&add.address)?; - let entry = self .certificates - .entry(address) + .entry(add.address.clone().into()) .or_insert_with(HashMap::new); if entry.contains_key(&fingerprint) { @@ -408,9 +404,7 @@ impl ConfigState { .map_err(|decode_error| StateError::RemoveCertificate(decode_error.to_string()))?, ); - let address = parse_socket_address(&remove.address)?; - - if let Some(index) = self.certificates.get_mut(&address) { + if let Some(index) = self.certificates.get_mut(&remove.address.clone().into()) { index.remove(&fingerprint); } @@ -422,18 +416,17 @@ impl ConfigState { /// - insert the new certificate with the new fingerprint as key /// - check that the new entry is present in the certificates hashmap fn replace_certificate(&mut self, replace: &ReplaceCertificate) -> Result<(), StateError> { - let address = parse_socket_address(&replace.address)?; - + let replace_address = replace.address.clone().into(); let old_fingerprint = Fingerprint( hex::decode(&replace.old_fingerprint) .map_err(|decode_error| StateError::RemoveCertificate(decode_error.to_string()))?, ); self.certificates - .get_mut(&address) + .get_mut(&replace_address) .ok_or(StateError::NotFound { kind: ObjectKind::Certificate, - id: address.to_string(), + id: replace.address.to_string(), })? .remove(&old_fingerprint); @@ -444,12 +437,12 @@ impl ConfigState { ); self.certificates - .get_mut(&address) + .get_mut(&replace_address) .map(|certs| certs.insert(new_fingerprint.clone(), replace.new_certificate.clone())); if !self .certificates - .get(&address) + .get(&replace_address) .ok_or(StateError::ReplaceCertificate( "Unlikely error. This entry in the certificate hashmap should be present" .to_string(), @@ -472,7 +465,7 @@ impl ConfigState { let tcp_frontend = TcpFrontend { cluster_id: front.cluster_id.clone(), - address: parse_socket_address(&front.address)?, + address: front.address.clone().into(), tags: front.tags.clone(), }; if tcp_frontends.contains(&tcp_frontend) { @@ -490,8 +483,6 @@ impl ConfigState { &mut self, front_to_remove: &RequestTcpFrontend, ) -> Result<(), StateError> { - let address = parse_socket_address(&front_to_remove.address)?; - let tcp_frontends = self.tcp_fronts .get_mut(&front_to_remove.cluster_id) @@ -501,7 +492,7 @@ impl ConfigState { })?; let len = tcp_frontends.len(); - tcp_frontends.retain(|front| front.address != address); + tcp_frontends.retain(|front| front.address != front_to_remove.address.clone().into()); if tcp_frontends.len() == len { return Err(StateError::NoChange); } @@ -510,7 +501,7 @@ impl ConfigState { fn add_backend(&mut self, add_backend: &AddBackend) -> Result<(), StateError> { let backend = Backend { - address: parse_socket_address(&add_backend.address)?, + address: add_backend.address.clone().into(), cluster_id: add_backend.cluster_id.clone(), backend_id: add_backend.backend_id.clone(), sticky_id: add_backend.sticky_id.clone(), @@ -540,9 +531,8 @@ impl ConfigState { })?; let len = backend_list.len(); - backend_list.retain(|b| { - b.backend_id != backend.backend_id || b.address.to_string() != backend.address - }); + let remove_address = backend.address.clone().into(); + backend_list.retain(|b| b.backend_id != backend.backend_id || b.address != remove_address); backend_list.sort(); if backend_list.len() == len { return Err(StateError::NoChange); @@ -607,7 +597,7 @@ impl ConfigState { for certificate_and_key in certs.values() { v.push( RequestType::AddCertificate(AddCertificate { - address: front.to_string(), + address: SocketAddress::from(*front), certificate: certificate_and_key.clone(), expired_at: None, }) @@ -645,7 +635,7 @@ impl ConfigState { { v.push( RequestType::ActivateListener(ActivateListener { - address: front.to_string(), + address: SocketAddress::from(*front), proxy: ListenerType::Http.into(), from_scm: false, }) @@ -661,7 +651,7 @@ impl ConfigState { { v.push( RequestType::ActivateListener(ActivateListener { - address: front.to_string(), + address: SocketAddress::from(*front), proxy: ListenerType::Https.into(), from_scm: false, }) @@ -676,7 +666,7 @@ impl ConfigState { { v.push( RequestType::ActivateListener(ActivateListener { - address: front.to_string(), + address: SocketAddress::from(*front), proxy: ListenerType::Tcp.into(), from_scm: false, }) @@ -689,18 +679,18 @@ impl ConfigState { pub fn diff(&self, other: &ConfigState) -> Vec { //pub tcp_listeners: HashMap, - let my_tcp_listeners: HashSet<&String> = self.tcp_listeners.keys().collect(); - let their_tcp_listeners: HashSet<&String> = other.tcp_listeners.keys().collect(); + let my_tcp_listeners: HashSet<&SocketAddr> = self.tcp_listeners.keys().collect(); + let their_tcp_listeners: HashSet<&SocketAddr> = other.tcp_listeners.keys().collect(); let removed_tcp_listeners = my_tcp_listeners.difference(&their_tcp_listeners); let added_tcp_listeners = their_tcp_listeners.difference(&my_tcp_listeners); - let my_http_listeners: HashSet<&String> = self.http_listeners.keys().collect(); - let their_http_listeners: HashSet<&String> = other.http_listeners.keys().collect(); + let my_http_listeners: HashSet<&SocketAddr> = self.http_listeners.keys().collect(); + let their_http_listeners: HashSet<&SocketAddr> = other.http_listeners.keys().collect(); let removed_http_listeners = my_http_listeners.difference(&their_http_listeners); let added_http_listeners = their_http_listeners.difference(&my_http_listeners); - let my_https_listeners: HashSet<&String> = self.https_listeners.keys().collect(); - let their_https_listeners: HashSet<&String> = other.https_listeners.keys().collect(); + let my_https_listeners: HashSet<&SocketAddr> = self.https_listeners.keys().collect(); + let their_https_listeners: HashSet<&SocketAddr> = other.https_listeners.keys().collect(); let removed_https_listeners = my_https_listeners.difference(&their_https_listeners); let added_https_listeners = their_https_listeners.difference(&my_https_listeners); @@ -710,7 +700,7 @@ impl ConfigState { if self.tcp_listeners[*address].active { v.push( RequestType::DeactivateListener(DeactivateListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Tcp.into(), to_scm: false, }) @@ -720,7 +710,7 @@ impl ConfigState { v.push( RequestType::RemoveListener(RemoveListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Tcp.into(), }) .into(), @@ -733,7 +723,7 @@ impl ConfigState { if other.tcp_listeners[*address].active { v.push( RequestType::ActivateListener(ActivateListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Tcp.into(), from_scm: false, }) @@ -746,7 +736,7 @@ impl ConfigState { if self.http_listeners[*address].active { v.push( RequestType::DeactivateListener(DeactivateListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Http.into(), to_scm: false, }) @@ -756,7 +746,7 @@ impl ConfigState { v.push( RequestType::RemoveListener(RemoveListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Http.into(), }) .into(), @@ -769,7 +759,7 @@ impl ConfigState { if other.http_listeners[*address].active { v.push( RequestType::ActivateListener(ActivateListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Http.into(), from_scm: false, }) @@ -782,7 +772,7 @@ impl ConfigState { if self.https_listeners[*address].active { v.push( RequestType::DeactivateListener(DeactivateListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Https.into(), to_scm: false, }) @@ -792,7 +782,7 @@ impl ConfigState { v.push( RequestType::RemoveListener(RemoveListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Https.into(), }) .into(), @@ -805,7 +795,7 @@ impl ConfigState { if other.https_listeners[*address].active { v.push( RequestType::ActivateListener(ActivateListener { - address: address.to_string(), + address: SocketAddress::from(**address), proxy: ListenerType::Https.into(), from_scm: false, }) @@ -821,7 +811,7 @@ impl ConfigState { if my_listener != their_listener { v.push( RequestType::RemoveListener(RemoveListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Tcp.into(), }) .into(), @@ -835,7 +825,7 @@ impl ConfigState { if my_listener.active && !their_listener.active { v.push( RequestType::DeactivateListener(DeactivateListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Tcp.into(), to_scm: false, }) @@ -846,7 +836,7 @@ impl ConfigState { if !my_listener.active && their_listener.active { v.push( RequestType::ActivateListener(ActivateListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Tcp.into(), from_scm: false, }) @@ -862,7 +852,7 @@ impl ConfigState { if my_listener != their_listener { v.push( RequestType::RemoveListener(RemoveListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Http.into(), }) .into(), @@ -876,7 +866,7 @@ impl ConfigState { if my_listener.active && !their_listener.active { v.push( RequestType::DeactivateListener(DeactivateListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Http.into(), to_scm: false, }) @@ -887,7 +877,7 @@ impl ConfigState { if !my_listener.active && their_listener.active { v.push( RequestType::ActivateListener(ActivateListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Http.into(), from_scm: false, }) @@ -903,7 +893,7 @@ impl ConfigState { if my_listener != their_listener { v.push( RequestType::RemoveListener(RemoveListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Https.into(), }) .into(), @@ -917,7 +907,7 @@ impl ConfigState { if my_listener.active && !their_listener.active { v.push( RequestType::DeactivateListener(DeactivateListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Https.into(), to_scm: false, }) @@ -928,7 +918,7 @@ impl ConfigState { if !my_listener.active && their_listener.active { v.push( RequestType::ActivateListener(ActivateListener { - address: addr.to_string(), + address: SocketAddress::from(**addr), proxy: ListenerType::Https.into(), from_scm: false, }) @@ -978,7 +968,7 @@ impl ConfigState { RequestType::RemoveBackend(RemoveBackend { cluster_id: backend.cluster_id.clone(), backend_id: backend.backend_id.clone(), - address: backend.address.to_string(), + address: SocketAddress::from(backend.address), }) .into(), ); @@ -994,7 +984,7 @@ impl ConfigState { RequestType::RemoveBackend(RemoveBackend { cluster_id: backend.cluster_id.clone(), backend_id: backend.backend_id.clone(), - address: backend.address.to_string(), + address: SocketAddress::from(backend.address), }) .into(), ); @@ -1091,7 +1081,7 @@ impl ConfigState { for &(address, fingerprint) in removed_certificates { v.push( RequestType::RemoveCertificate(RemoveCertificate { - address: address.to_string(), + address: SocketAddress::from(address), fingerprint: fingerprint.to_string(), }) .into(), @@ -1106,7 +1096,7 @@ impl ConfigState { { v.push( RequestType::AddCertificate(AddCertificate { - address: address.to_string(), + address: SocketAddress::from(address), certificate: certificate_and_key.clone(), expired_at: None, }) @@ -1373,9 +1363,21 @@ impl ConfigState { pub fn list_listeners(&self) -> ListenersList { ListenersList { - http_listeners: self.http_listeners.clone(), - https_listeners: self.https_listeners.clone(), - tcp_listeners: self.tcp_listeners.clone(), + http_listeners: self + .http_listeners + .iter() + .map(|(addr, listener)| (addr.to_string(), listener.clone())) + .collect(), + https_listeners: self + .https_listeners + .iter() + .map(|(addr, listener)| (addr.to_string(), listener.clone())) + .collect(), + tcp_listeners: self + .tcp_listeners + .iter() + .map(|(addr, listener)| (addr.to_string(), listener.clone())) + .collect(), } } @@ -1411,15 +1413,6 @@ impl ConfigState { } } -fn parse_socket_address(address: &str) -> Result { - address - .parse::() - .map_err(|parse_error| StateError::WrongSocketAddress { - address: address.to_owned(), - error: parse_error.to_string(), - }) -} - fn domain_check( front_hostname: &str, front_path_rule: &PathRule, @@ -1535,7 +1528,7 @@ mod tests { cluster_id: Some(String::from("cluster_1")), hostname: String::from("lolcatho.st:8080"), path: PathRule::prefix(String::from("/")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), position: RulePosition::Tree.into(), ..Default::default() }) @@ -1548,7 +1541,7 @@ mod tests { cluster_id: Some(String::from("cluster_2")), hostname: String::from("test.local"), path: PathRule::prefix(String::from("/abc")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), position: RulePosition::Pre.into(), ..Default::default() }) @@ -1560,7 +1553,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), - address: "127.0.0.1:1026".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), ..Default::default() }) .into(), @@ -1571,7 +1564,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-1"), - address: "127.0.0.2:1027".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1027), ..Default::default() }) .into(), @@ -1582,7 +1575,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_2"), backend_id: String::from("cluster_2-0"), - address: "192.167.1.2:1026".parse().unwrap(), + address: SocketAddress::new_v4(192, 167, 1, 2, 1026), ..Default::default() }) .into(), @@ -1593,7 +1586,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-3"), - address: "192.168.1.3:1027".parse().unwrap(), + address: SocketAddress::new_v4(192, 168, 1, 3, 1027), ..Default::default() }) .into(), @@ -1604,7 +1597,7 @@ mod tests { &RequestType::RemoveBackend(RemoveBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-3"), - address: "192.168.1.3:1027".parse().unwrap(), + address: SocketAddress::new_v4(192, 168, 1, 3, 1027), }) .into(), ) @@ -1630,7 +1623,7 @@ mod tests { cluster_id: Some(String::from("cluster_1")), hostname: String::from("lolcatho.st:8080"), path: PathRule::prefix(String::from("/")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), position: RulePosition::Post.into(), ..Default::default() }) @@ -1643,7 +1636,7 @@ mod tests { cluster_id: Some(String::from("cluster_2")), hostname: String::from("test.local"), path: PathRule::prefix(String::from("/abc")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), ..Default::default() }) .into(), @@ -1654,7 +1647,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), - address: "127.0.0.1:1026".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1666,7 +1659,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-1"), - address: "127.0.0.2:1027".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 2, 1027), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1678,7 +1671,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_2"), backend_id: String::from("cluster_2-0"), - address: "192.167.1.2:1026".parse().unwrap(), + address: SocketAddress::new_v4(192, 167, 1, 2, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1704,7 +1697,7 @@ mod tests { cluster_id: Some(String::from("cluster_1")), hostname: String::from("lolcatho.st:8080"), path: PathRule::prefix(String::from("/")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), position: RulePosition::Post.into(), ..Default::default() }) @@ -1716,7 +1709,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), - address: "127.0.0.1:1026".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1728,7 +1721,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-1"), - address: "127.0.0.2:1027".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 2, 1027), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1740,7 +1733,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-2"), - address: "127.0.0.2:1028".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 2, 1028), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1764,20 +1757,20 @@ mod tests { cluster_id: Some(String::from("cluster_2")), hostname: String::from("test.local"), path: PathRule::prefix(String::from("/abc")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), ..Default::default() }) .into(), RequestType::RemoveBackend(RemoveBackend { cluster_id: String::from("cluster_2"), backend_id: String::from("cluster_2-0"), - address: "192.167.1.2:1026".to_string(), + address: SocketAddress::new_v4(192, 167, 1, 2, 1026), }) .into(), RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-2"), - address: "127.0.0.2:1028".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 2, 1028), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1806,7 +1799,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-2"), - address: "127.0.0.2:1028".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 2, 1028), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1828,7 +1821,7 @@ mod tests { cluster_id: Some(String::from("MyCluster_1")), hostname: String::from("lolcatho.st"), path: PathRule::prefix(String::from("")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), ..Default::default() }; @@ -1836,7 +1829,7 @@ mod tests { cluster_id: Some(String::from("MyCluster_1")), hostname: String::from("lolcatho.st"), path: PathRule::prefix(String::from("")), - address: "0.0.0.0:8443".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), ..Default::default() }; @@ -1844,7 +1837,7 @@ mod tests { cluster_id: Some(String::from("MyCluster_2")), hostname: String::from("lolcatho.st"), path: PathRule::prefix(String::from("/api")), - address: "0.0.0.0:8080".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), ..Default::default() }; @@ -1852,7 +1845,7 @@ mod tests { cluster_id: Some(String::from("MyCluster_2")), hostname: String::from("lolcatho.st"), path: PathRule::prefix(String::from("/api")), - address: "0.0.0.0:8443".to_string(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), ..Default::default() }; @@ -1905,7 +1898,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }) @@ -1948,7 +1941,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: format!("cluster_1-{i}"), - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), ..Default::default() }) .into(), @@ -1961,7 +1954,7 @@ mod tests { let remove_backend_2 = RequestType::RemoveBackend(RemoveBackend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), }) .into(); @@ -1995,7 +1988,7 @@ mod tests { &RequestType::AddBackend(AddBackend { cluster_id: String::from("cluster_1"), backend_id: format!("cluster_1-{i}"), - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), ..Default::default() }) .into(), @@ -2014,7 +2007,7 @@ mod tests { &RequestType::RemoveBackend(RemoveBackend { cluster_id: String::from("cluster_1"), backend_id: format!("cluster_1-{j}"), - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), }) .into(), ); @@ -2029,7 +2022,7 @@ mod tests { state .dispatch( &RequestType::AddTcpListener(TcpListenerConfig { - address: "0.0.0.0:1234".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 1234), ..Default::default() }) .into(), @@ -2038,7 +2031,7 @@ mod tests { state .dispatch( &RequestType::ActivateListener(ActivateListener { - address: "0.0.0.0:1234".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 1234), proxy: ListenerType::Tcp.into(), from_scm: false, }) @@ -2048,7 +2041,7 @@ mod tests { state .dispatch( &RequestType::AddHttpListener(HttpListenerConfig { - address: "0.0.0.0:8080".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), ..Default::default() }) .into(), @@ -2057,7 +2050,7 @@ mod tests { state .dispatch( &RequestType::AddHttpsListener(HttpsListenerConfig { - address: "0.0.0.0:8443".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), ..Default::default() }) .into(), @@ -2066,7 +2059,7 @@ mod tests { state .dispatch( &RequestType::ActivateListener(ActivateListener { - address: "0.0.0.0:8443".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), proxy: ListenerType::Https.into(), from_scm: false, }) @@ -2078,7 +2071,7 @@ mod tests { state2 .dispatch( &RequestType::AddTcpListener(TcpListenerConfig { - address: "0.0.0.0:1234".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 1234), expect_proxy: true, ..Default::default() }) @@ -2088,7 +2081,7 @@ mod tests { state2 .dispatch( &RequestType::AddHttpListener(HttpListenerConfig { - address: "0.0.0.0:8080".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), answer_404: "test".to_string(), ..Default::default() }) @@ -2098,7 +2091,7 @@ mod tests { state2 .dispatch( &RequestType::ActivateListener(ActivateListener { - address: "0.0.0.0:8080".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), proxy: ListenerType::Http.into(), from_scm: false, }) @@ -2108,7 +2101,7 @@ mod tests { state2 .dispatch( &RequestType::AddHttpsListener(HttpsListenerConfig { - address: "0.0.0.0:8443".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), answer_404: String::from("test"), ..Default::default() }) @@ -2118,7 +2111,7 @@ mod tests { state2 .dispatch( &RequestType::ActivateListener(ActivateListener { - address: "0.0.0.0:8443".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), proxy: ListenerType::Https.into(), from_scm: false, }) @@ -2128,46 +2121,46 @@ mod tests { let e: Vec = vec![ RequestType::RemoveListener(RemoveListener { - address: "0.0.0.0:1234".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 1234), proxy: ListenerType::Tcp.into(), }) .into(), RequestType::AddTcpListener(TcpListenerConfig { - address: "0.0.0.0:1234".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 1234), expect_proxy: true, ..Default::default() }) .into(), RequestType::DeactivateListener(DeactivateListener { - address: "0.0.0.0:1234".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 1234), proxy: ListenerType::Tcp.into(), to_scm: false, }) .into(), RequestType::RemoveListener(RemoveListener { - address: "0.0.0.0:8080".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), proxy: ListenerType::Http.into(), }) .into(), RequestType::AddHttpListener(HttpListenerConfig { - address: "0.0.0.0:8080".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), answer_404: String::from("test"), ..Default::default() }) .into(), RequestType::ActivateListener(ActivateListener { - address: "0.0.0.0:8080".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8080), proxy: ListenerType::Http.into(), from_scm: false, }) .into(), RequestType::RemoveListener(RemoveListener { - address: "0.0.0.0:8443".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), proxy: ListenerType::Https.into(), }) .into(), RequestType::AddHttpsListener(HttpsListenerConfig { - address: "0.0.0.0:8443".parse().unwrap(), + address: SocketAddress::new_v4(0, 0, 0, 0, 8443), answer_404: String::from("test"), ..Default::default() }) @@ -2196,7 +2189,7 @@ mod tests { names: vec!["lolcatho.st".to_string()], }; let add_certificate = AddCertificate { - address: "127.0.0.1:8080".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8080), certificate: certificate_and_key, expired_at: None, }; diff --git a/e2e/src/sozu/worker.rs b/e2e/src/sozu/worker.rs index 1527a5115..cf16eea5a 100644 --- a/e2e/src/sozu/worker.rs +++ b/e2e/src/sozu/worker.rs @@ -282,11 +282,11 @@ impl Worker { pub fn default_tcp_frontend>( cluster_id: S, - address: String, + address: SocketAddr, ) -> RequestTcpFrontend { RequestTcpFrontend { cluster_id: cluster_id.into(), - address, + address: address.into(), ..Default::default() } } @@ -297,7 +297,7 @@ impl Worker { ) -> RequestHttpFrontend { RequestHttpFrontend { cluster_id: Some(cluster_id.into()), - address: address.to_string(), + address: address.into(), hostname: String::from("localhost"), path: PathRule::prefix(String::from("/")), position: RulePosition::Tree.into(), @@ -308,13 +308,13 @@ impl Worker { pub fn default_backend, S2: Into>( cluster_id: S1, backend_id: S2, - address: String, + address: SocketAddr, sticky_id: Option, ) -> AddBackend { AddBackend { cluster_id: cluster_id.into(), backend_id: backend_id.into(), - address, + address: address.into(), load_balancing_parameters: Some(LoadBalancingParams::default()), sticky_id, backup: None, diff --git a/e2e/src/tests/mod.rs b/e2e/src/tests/mod.rs index f7588f87b..1210e171e 100644 --- a/e2e/src/tests/mod.rs +++ b/e2e/src/tests/mod.rs @@ -22,6 +22,8 @@ use crate::{ sozu::worker::Worker, }; +use self::tests::create_local_address; + #[derive(PartialEq, Eq, Debug)] pub enum State { Success, @@ -55,14 +57,14 @@ pub fn setup_test>( worker.send_proxy_request(Request { request_type: Some(RequestType::AddHttpListener( - ListenerBuilder::new_http(front_address) + ListenerBuilder::new_http(front_address.into()) .to_http(None) .unwrap(), )), }); worker.send_proxy_request(Request { request_type: Some(RequestType::ActivateListener(ActivateListener { - address: front_address.to_string(), + address: front_address.into(), proxy: ListenerType::Http.into(), from_scm: false, })), @@ -82,21 +84,21 @@ pub fn setup_test>( let mut backends = Vec::new(); for i in 0..nb_backends { - let back_address: SocketAddr = format!("127.0.0.1:{}", provide_port()) - .parse() - .expect("could not parse back address"); - worker.send_proxy_request(Request { - request_type: Some(RequestType::AddBackend(Worker::default_backend( + let back_address = create_local_address(); + + worker.send_proxy_request( + RequestType::AddBackend(Worker::default_backend( "cluster_0", format!("cluster_0-{i}"), - back_address.to_string(), + back_address.into(), if should_stick { Some(format!("sticky_cluster_0-{i}")) } else { None }, - ))), - }); + )) + .into(), + ); backends.push(back_address); } diff --git a/e2e/src/tests/tests.rs b/e2e/src/tests/tests.rs index 27e35737b..36f2a171f 100644 --- a/e2e/src/tests/tests.rs +++ b/e2e/src/tests/tests.rs @@ -10,7 +10,7 @@ use sozu_command_lib::{ logging::setup_logging, proto::command::{ request::RequestType, ActivateListener, AddCertificate, CertificateAndKey, ListenerType, - RemoveBackend, RequestHttpFrontend, + RemoveBackend, RequestHttpFrontend, SocketAddress, }, scm_socket::Listeners, state::ConfigState, @@ -29,7 +29,7 @@ use crate::{ tests::{provide_port, repeat_until_error_or, setup_async_test, setup_sync_test, State}, }; -fn create_local_address() -> SocketAddr { +pub fn create_local_address() -> SocketAddr { let address: SocketAddr = format!("127.0.0.1:{}", provide_port()) .parse() .expect("could not parse front address"); @@ -295,12 +295,12 @@ pub fn try_issue_810_panic(part2: bool) -> State { let mut worker = Worker::start_new_worker("810-PANIC", config, &listeners, state); worker.send_proxy_request_type(RequestType::AddTcpListener( - ListenerBuilder::new_tcp(front_address) + ListenerBuilder::new_tcp(front_address.into()) .to_tcp(None) .unwrap(), )); worker.send_proxy_request_type(RequestType::ActivateListener(ActivateListener { - address: front_address.to_string(), + address: front_address.into(), proxy: ListenerType::Tcp.into(), from_scm: false, })); @@ -310,13 +310,13 @@ pub fn try_issue_810_panic(part2: bool) -> State { ))); worker.send_proxy_request_type(RequestType::AddTcpFrontend(Worker::default_tcp_frontend( "cluster_0", - front_address.to_string(), + front_address, ))); worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0", - back_address.to_string(), + back_address, None, ))); worker.read_to_last(); @@ -356,22 +356,20 @@ pub fn try_issue_810_panic(part2: bool) -> State { pub fn try_tls_endpoint() -> State { let front_port = provide_port(); - let front_address: SocketAddr = format!("127.0.0.1:{}", front_port) - .parse() - .expect("could not parse front address"); + let front_address = SocketAddress::new_v4(127, 0, 0, 1, front_port); let back_address = create_local_address(); let (config, listeners, state) = Worker::empty_config(); let mut worker = Worker::start_new_worker("TLS-ENDPOINT", config, &listeners, state); worker.send_proxy_request_type(RequestType::AddHttpsListener( - ListenerBuilder::new_https(front_address) + ListenerBuilder::new_https(front_address.clone().into()) .to_tls(None) .unwrap(), )); worker.send_proxy_request_type(RequestType::ActivateListener(ActivateListener { - address: front_address.to_string(), + address: front_address.clone().into(), proxy: ListenerType::Https.into(), from_scm: false, })); @@ -384,7 +382,7 @@ pub fn try_tls_endpoint() -> State { let hostname = "localhost".to_string(); worker.send_proxy_request_type(RequestType::AddHttpsFrontend(RequestHttpFrontend { hostname: hostname.to_owned(), - ..Worker::default_http_frontend("cluster_0", front_address) + ..Worker::default_http_frontend("cluster_0", front_address.clone().into()) })); let certificate_and_key = CertificateAndKey { @@ -395,7 +393,7 @@ pub fn try_tls_endpoint() -> State { names: vec![], }; let add_certificate = AddCertificate { - address: front_address.to_string(), + address: front_address.into(), certificate: certificate_and_key, expired_at: None, }; @@ -404,7 +402,7 @@ pub fn try_tls_endpoint() -> State { worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0", - back_address.to_string(), + back_address, None, ))); worker.read_to_last(); @@ -643,12 +641,12 @@ fn try_http_behaviors() -> State { let mut worker = Worker::start_new_worker("BEHAVE-WORKER", config, &listeners, state); worker.send_proxy_request_type(RequestType::AddHttpListener( - ListenerBuilder::new_http(front_address) + ListenerBuilder::new_http(front_address.into()) .to_http(None) .unwrap(), )); worker.send_proxy_request_type(RequestType::ActivateListener(ActivateListener { - address: front_address.to_string(), + address: front_address.into(), proxy: ListenerType::Http.into(), from_scm: false, })); @@ -689,7 +687,7 @@ fn try_http_behaviors() -> State { worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0".to_string(), - back_address.to_string(), + back_address, None, ))); worker.read_to_last(); @@ -731,12 +729,12 @@ fn try_http_behaviors() -> State { worker.send_proxy_request_type(RequestType::RemoveBackend(RemoveBackend { cluster_id: String::from("cluster_0"), backend_id: String::from("cluster_0-0"), - address: back_address.to_string(), + address: back_address.into(), })); worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0".to_string(), - back_address.to_string(), + back_address, None, ))); backend.disconnect(); @@ -793,12 +791,12 @@ fn try_http_behaviors() -> State { worker.send_proxy_request_type(RequestType::RemoveBackend(RemoveBackend { cluster_id: String::from("cluster_0"), backend_id: String::from("cluster_0-0"), - address: back_address.to_string(), + address: back_address.into(), })); worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0".to_string(), - back_address.to_string(), + back_address, None, ))); backend.disconnect(); @@ -1012,7 +1010,7 @@ pub fn try_blue_geen() -> State { worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0", - primary_address.to_string(), + primary_address.into(), None, ))); worker.read_to_last(); @@ -1031,7 +1029,7 @@ pub fn try_blue_geen() -> State { worker.send_proxy_request_type(RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-1", - secondary_address.to_string(), + secondary_address.into(), None, ))); worker.read_to_last(); @@ -1043,7 +1041,7 @@ pub fn try_blue_geen() -> State { worker.send_proxy_request_type(RequestType::RemoveBackend(RemoveBackend { cluster_id: "cluster_0".to_string(), backend_id: "cluster_0-0".to_string(), - address: primary_address.to_string(), + address: primary_address.into(), })); worker.read_to_last(); @@ -1464,7 +1462,7 @@ fn try_wildcard() -> State { let mut worker = Worker::start_new_worker("WLD_CRD", config, &listeners, state); worker.send_proxy_request( RequestType::AddHttpListener( - ListenerBuilder::new_http(front_address) + ListenerBuilder::new_http(front_address.into()) .to_http(None) .unwrap(), ) @@ -1472,7 +1470,7 @@ fn try_wildcard() -> State { ); worker.send_proxy_request( RequestType::ActivateListener(ActivateListener { - address: front_address.to_string(), + address: front_address.into(), proxy: ListenerType::Http.into(), from_scm: false, }) @@ -1489,7 +1487,7 @@ fn try_wildcard() -> State { worker.send_proxy_request( RequestType::AddHttpFrontend(RequestHttpFrontend { cluster_id: Some("cluster_0".to_string()), - address: front_address.to_string(), + address: front_address.into(), hostname: String::from("*.sozu.io"), path: PathRule::prefix(String::from("")), position: RulePosition::Tree.into(), @@ -1503,7 +1501,7 @@ fn try_wildcard() -> State { RequestType::AddBackend(Worker::default_backend( "cluster_0", "cluster_0-0", - back_address.to_string(), + back_address, None, )) .into(), @@ -1536,7 +1534,7 @@ fn try_wildcard() -> State { worker.send_proxy_request( RequestType::AddHttpFrontend(RequestHttpFrontend { cluster_id: Some("cluster_1".to_string()), - address: front_address.to_string(), + address: front_address.into(), hostname: String::from("*.sozu.io"), path: PathRule::prefix(String::from("/api")), position: RulePosition::Tree.into(), @@ -1549,7 +1547,7 @@ fn try_wildcard() -> State { RequestType::AddBackend(Worker::default_backend( "cluster_1", "cluster_1-0", - back_address.to_string(), + back_address, None, )) .into(), diff --git a/lib/examples/http.rs b/lib/examples/http.rs index 7c38f85a2..81b2e77b1 100644 --- a/lib/examples/http.rs +++ b/lib/examples/http.rs @@ -14,7 +14,7 @@ use sozu_command_lib::{ logging::setup_logging, proto::command::{ request::RequestType, AddBackend, Cluster, LoadBalancingAlgorithms, LoadBalancingParams, - PathRule, RequestHttpFrontend, RulePosition, + PathRule, RequestHttpFrontend, RulePosition, SocketAddress, }, request::WorkerRequest, response::WorkerResponse, @@ -25,7 +25,7 @@ fn main() -> anyhow::Result<()> { info!("starting up"); - let http_listener = ListenerBuilder::new_http("127.0.0.1:8080") + let http_listener = ListenerBuilder::new_http(SocketAddress::new_v4(127, 0, 0, 1, 8080)) .to_http(None) .expect("Could not create HTTP listener"); @@ -57,7 +57,7 @@ fn main() -> anyhow::Result<()> { let http_front = RequestHttpFrontend { cluster_id: Some("my-cluster".to_string()), - address: "127.0.0.1:8080".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8080), hostname: "example.com".to_string(), path: PathRule::prefix(String::from("/")), position: RulePosition::Pre.into(), @@ -70,7 +70,7 @@ fn main() -> anyhow::Result<()> { let http_backend = AddBackend { cluster_id: "my-cluster".to_string(), backend_id: "test-backend".to_string(), - address: "127.0.0.1:8000".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8080), load_balancing_parameters: Some(LoadBalancingParams::default()), ..Default::default() }; diff --git a/lib/examples/https.rs b/lib/examples/https.rs index 036ade116..e0939e210 100644 --- a/lib/examples/https.rs +++ b/lib/examples/https.rs @@ -15,7 +15,7 @@ use sozu_command_lib::{ logging::setup_logging, proto::command::{ request::RequestType, AddBackend, AddCertificate, CertificateAndKey, LoadBalancingParams, - PathRule, RequestHttpFrontend, + PathRule, RequestHttpFrontend, SocketAddress, }, request::WorkerRequest, }; @@ -26,16 +26,15 @@ fn main() -> anyhow::Result<()> { info!("MAIN\tstarting up"); sozu_lib::metrics::setup( - &"127.0.0.1:8125" - .parse() - .with_context(|| "Could not parse address for metrics setup")?, + &SocketAddress::new_v4(127, 0, 0, 1, 8125).into(), "main", false, None, ); gauge!("sozu.TEST", 42); - let http_listener = ListenerBuilder::new_http("127.0.0.1:8080").to_http(None)?; + let http_listener = + ListenerBuilder::new_http(SocketAddress::new_v4(127, 0, 0, 1, 8080)).to_http(None)?; let (mut command, channel) = Channel::generate(1000, 10000).with_context(|| "should create a channel")?; @@ -52,7 +51,7 @@ fn main() -> anyhow::Result<()> { let http_front = RequestHttpFrontend { cluster_id: Some(String::from("cluster_1")), - address: "127.0.0.1:8080".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8080), hostname: String::from("lolcatho.st"), path: PathRule::prefix(String::from("/")), ..Default::default() @@ -62,7 +61,7 @@ fn main() -> anyhow::Result<()> { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), sticky_id: None, - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), backup: None, }; @@ -80,7 +79,8 @@ fn main() -> anyhow::Result<()> { info!("MAIN\tHTTP -> {:?}", command.read_message()); info!("MAIN\tHTTP -> {:?}", command.read_message()); - let https_listener = ListenerBuilder::new_https("127.0.0.1:8443").to_tls(None)?; + let https_listener = + ListenerBuilder::new_https(SocketAddress::new_v4(127, 0, 0, 1, 8443)).to_tls(None)?; let (mut command2, channel2) = Channel::generate(1000, 10000).with_context(|| "should create a channel")?; @@ -108,9 +108,7 @@ fn main() -> anyhow::Result<()> { command2.write_message(&WorkerRequest { id: String::from("ID_IJKL1"), content: RequestType::AddCertificate(AddCertificate { - address: "127.0.0.1:8443" - .parse() - .with_context(|| "Could not parse certificate address")?, + address: SocketAddress::new_v4(127, 0, 0, 1, 8443), certificate: certificate_and_key, expired_at: None, }) @@ -119,7 +117,7 @@ fn main() -> anyhow::Result<()> { let tls_front = RequestHttpFrontend { cluster_id: Some(String::from("cluster_1")), - address: "127.0.0.1:8443".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8443), hostname: String::from("lolcatho.st"), path: PathRule::prefix(String::from("/")), ..Default::default() @@ -133,7 +131,7 @@ fn main() -> anyhow::Result<()> { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), sticky_id: None, - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), backup: None, }; @@ -157,9 +155,7 @@ fn main() -> anyhow::Result<()> { command2.write_message(&WorkerRequest { id: String::from("ID_QRST1"), content: RequestType::AddCertificate(AddCertificate { - address: "127.0.0.1:8443" - .parse() - .with_context(|| "Could not parse certificate address")?, + address: SocketAddress::new_v4(127, 0, 0, 1, 8443), certificate: certificate_and_key2, expired_at: None, }) @@ -168,7 +164,7 @@ fn main() -> anyhow::Result<()> { let tls_front2 = RequestHttpFrontend { cluster_id: Some(String::from("cluster_2")), - address: "127.0.0.1:8443".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8443), hostname: String::from("test.local"), path: PathRule::prefix(String::from("/")), ..Default::default() @@ -183,7 +179,7 @@ fn main() -> anyhow::Result<()> { cluster_id: String::from("cluster_2"), backend_id: String::from("cluster_2-0"), sticky_id: None, - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), backup: None, }; diff --git a/lib/examples/tcp.rs b/lib/examples/tcp.rs index 4ba4576ae..fc255bd8c 100644 --- a/lib/examples/tcp.rs +++ b/lib/examples/tcp.rs @@ -11,7 +11,7 @@ use sozu_command_lib::{ channel::Channel, logging::setup_logging, proto::command::{ - request::RequestType, AddBackend, LoadBalancingParams, RequestTcpFrontend, + request::RequestType, AddBackend, LoadBalancingParams, RequestTcpFrontend, SocketAddress, TcpListenerConfig, }, request::WorkerRequest, @@ -30,7 +30,7 @@ fn main() -> anyhow::Result<()> { let max_buffers = 500; let buffer_size = 16384; let listener = TcpListenerConfig { - address: "127.0.0.1:8080".parse().expect("could not parse address"), + address: SocketAddress::new_v4(127, 0, 0, 1, 8080), ..Default::default() }; setup_logging("stdout", None, "debug", "TCP"); @@ -39,13 +39,13 @@ fn main() -> anyhow::Result<()> { let tcp_front = RequestTcpFrontend { cluster_id: String::from("test"), - address: "127.0.0.1:8080".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 8080), ..Default::default() }; let tcp_backend = AddBackend { cluster_id: String::from("test"), backend_id: String::from("test-0"), - address: "127.0.0.1:1026".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1026), load_balancing_parameters: Some(LoadBalancingParams::default()), sticky_id: None, backup: None, diff --git a/lib/src/backends.rs b/lib/src/backends.rs index 141bbd108..1d054b162 100644 --- a/lib/src/backends.rs +++ b/lib/src/backends.rs @@ -169,7 +169,7 @@ impl std::ops::Drop for Backend { server::push_event(Event { kind: EventKind::RemovedBackendHasNoConnections as i32, backend_id: Some(self.backend_id.clone()), - address: Some(self.address.to_string()), + address: Some(self.address.into()), cluster_id: None, }); } diff --git a/lib/src/http.rs b/lib/src/http.rs index 2c97976e1..0b64695ce 100644 --- a/lib/src/http.rs +++ b/lib/src/http.rs @@ -523,11 +523,12 @@ impl HttpProxy { pub fn remove_listener(&mut self, remove: RemoveListener) -> Result<(), ProxyError> { let len = self.listeners.len(); + let remove_address = remove.address.clone().into(); self.listeners - .retain(|_, l| l.borrow().address.to_string() != remove.address); + .retain(|_, l| l.borrow().address != remove_address); if !self.listeners.len() < len { - info!("no HTTP listener to remove at address {:?}", remove.address); + info!("no HTTP listener to remove at address {:?}", remove_address); } Ok(()) } @@ -714,16 +715,9 @@ impl HttpProxy { impl HttpListener { pub fn new(config: HttpListenerConfig, token: Token) -> Result { - let address = config - .address - .parse::() - .map_err(|parse_error| ListenerError::SocketParse { - address: config.address.clone(), - error: parse_error.to_string(), - })?; Ok(HttpListener { active: false, - address, + address: config.address.clone().into(), answers: Rc::new(RefCell::new(HttpAnswers::new( &config.answer_404, &config.answer_503, @@ -744,15 +738,16 @@ impl HttpListener { if self.active { return Ok(self.token); } + let address: SocketAddr = self.config.address.clone().into(); let mut listener = match tcp_listener { Some(tcp_listener) => tcp_listener, - None => server_bind(self.config.address.clone()).map_err(|server_bind_error| { - ListenerError::Activation { - address: self.config.address.clone(), + None => { + server_bind(address).map_err(|server_bind_error| ListenerError::Activation { + address, error: server_bind_error.to_string(), - } - })?, + })? + } }; registry @@ -916,13 +911,10 @@ impl ProxyConfiguration for HttpProxy { return Err(AcceptError::RegisterError); } - let public_address: SocketAddr = owned - .config - .public_address - .clone() - .unwrap_or(owned.config.address.clone()) - .parse() - .map_err(|_| AcceptError::WrongSocketAddress)?; + let public_address: SocketAddr = match owned.config.public_address.clone() { + Some(pub_addr) => pub_addr.into(), + None => owned.config.address.clone().into(), + }; let session = HttpSession::new( owned.answers.clone(), @@ -1001,10 +993,7 @@ pub mod testing { max_buffers: usize, buffer_size: usize, ) -> anyhow::Result<()> { - let address = config - .address - .parse() - .with_context(|| "Could not parse socket address")?; + let address = config.address.clone().into(); let ServerParts { event_loop, @@ -1064,6 +1053,7 @@ mod tests { use super::testing::start_http_worker; use super::*; + use sozu_command::proto::command::SocketAddress; use crate::sozu_command::{ channel::Channel, @@ -1075,9 +1065,8 @@ mod tests { use std::{ io::{Read, Write}, - net::{SocketAddr, TcpStream}, + net::TcpStream, str, - str::FromStr, sync::{Arc, Barrier}, thread, time::Duration, @@ -1103,7 +1092,7 @@ mod tests { start_server(1025, barrier.clone()); barrier.wait(); - let config = ListenerBuilder::new_http("127.0.0.1:1024") + let config = ListenerBuilder::new_http(SocketAddress::new_v4(127, 0, 0, 1, 1024)) .to_http(None) .expect("could not create listener config"); @@ -1116,7 +1105,7 @@ mod tests { let front = RequestHttpFrontend { cluster_id: Some(String::from("cluster_1")), - address: "127.0.0.1:1024".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1024), hostname: String::from("localhost"), path: PathRule::prefix(String::from("/")), ..Default::default() @@ -1130,7 +1119,7 @@ mod tests { let backend = Backend { cluster_id: String::from("cluster_1"), backend_id: String::from("cluster_1-0"), - address: "127.0.0.1:1025".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1025).into(), load_balancing_parameters: Some(LoadBalancingParams::default()), sticky_id: None, backup: None, @@ -1185,7 +1174,7 @@ mod tests { start_server(1028, barrier.clone()); barrier.wait(); - let config = ListenerBuilder::new_http("127.0.0.1:1031") + let config = ListenerBuilder::new_http(SocketAddress::new_v4(127, 0, 0, 1, 1031)) .to_http(None) .expect("could not create listener config"); @@ -1198,7 +1187,7 @@ mod tests { }); let front = RequestHttpFrontend { - address: "127.0.0.1:1031".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1031), hostname: String::from("localhost"), path: PathRule::prefix(String::from("/")), cluster_id: Some(String::from("cluster_1")), @@ -1211,7 +1200,7 @@ mod tests { }) .unwrap(); let backend = Backend { - address: "127.0.0.1:1028".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1028).into(), backend_id: String::from("cluster_1-0"), backup: None, cluster_id: String::from("cluster_1"), @@ -1295,7 +1284,7 @@ mod tests { fn https_redirect() { setup_test_logger!(); - let config = ListenerBuilder::new_http("127.0.0.1:1041") + let config = ListenerBuilder::new_http(SocketAddress::new_v4(127, 0, 0, 1, 1041)) .to_http(None) .expect("could not create listener config"); @@ -1320,7 +1309,7 @@ mod tests { }) .unwrap(); let front = RequestHttpFrontend { - address: "127.0.0.1:1041".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1041), hostname: String::from("localhost"), path: PathRule::prefix(String::from("/")), cluster_id: Some(String::from("cluster_1")), @@ -1333,7 +1322,7 @@ mod tests { }) .unwrap(); let backend = Backend { - address: "127.0.0.1:1040".parse().unwrap(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1040).into(), backend_id: String::from("cluster_1-0"), backup: None, cluster_id: String::from("cluster_1"), @@ -1468,16 +1457,15 @@ mod tests { }) .expect("Could not add http frontend"); - let address: SocketAddr = - FromStr::from_str("127.0.0.1:1030").expect("could not parse address"); + let address = SocketAddress::new_v4(127, 0, 0, 1, 1030); - let default_config = ListenerBuilder::new_http(address) + let default_config = ListenerBuilder::new_http(address.clone()) .to_http(None) .expect("Could not create default HTTP listener config"); let listener = HttpListener { listener: None, - address, + address: address.into(), fronts, answers: Rc::new(RefCell::new(HttpAnswers::new( "HTTP/1.1 404 Not Found\r\n\r\n", diff --git a/lib/src/https.rs b/lib/src/https.rs index c1927a2c3..e50d0c385 100644 --- a/lib/src/https.rs +++ b/lib/src/https.rs @@ -657,17 +657,9 @@ impl HttpsListener { let server_config = Arc::new(Self::create_rustls_context(&config, resolver.to_owned())?); - let address = config - .address - .parse::() - .map_err(|parse_error| ListenerError::SocketParse { - address: config.address.clone(), - error: parse_error.to_string(), - })?; - Ok(HttpsListener { listener: None, - address, + address: config.address.clone().into(), resolver, rustls_details: server_config, active: false, @@ -690,15 +682,16 @@ impl HttpsListener { if self.active { return Ok(self.token); } + let address: StdSocketAddr = self.config.address.clone().into(); let mut listener = match tcp_listener { Some(tcp_listener) => tcp_listener, - None => server_bind(self.config.address.clone()).map_err(|server_bind_error| { - ListenerError::Activation { - address: self.config.address.clone(), + None => { + server_bind(address).map_err(|server_bind_error| ListenerError::Activation { + address, error: server_bind_error.to_string(), - } - })?, + })? + } }; registry @@ -857,14 +850,12 @@ impl HttpsProxy { ) -> Result, ProxyError> { let len = self.listeners.len(); + let remove_address = remove.address.clone().into(); self.listeners - .retain(|_, listener| listener.borrow().address.to_string() != remove.address); + .retain(|_, listener| listener.borrow().address != remove_address); if !self.listeners.len() < len { - info!( - "no HTTPS listener to remove at address {:?}", - remove.address - ) + info!("no HTTPS listener to remove at address {}", remove_address) } Ok(None) } @@ -944,7 +935,7 @@ impl HttpsProxy { .collect(); CertificatesByAddress { - address: owned.address.to_string(), + address: owned.address.into(), certificate_summaries, } }) @@ -979,7 +970,7 @@ impl HttpsProxy { }); } CertificatesByAddress { - address: owned.address.to_string(), + address: owned.address.into(), certificate_summaries, } }) @@ -1134,13 +1125,7 @@ impl HttpsProxy { &mut self, add_certificate: AddCertificate, ) -> Result, ProxyError> { - let address = add_certificate - .address - .parse::() - .map_err(|parse_error| ProxyError::SocketParse { - address: add_certificate.address.clone(), - error: parse_error.to_string(), - })?; + let address = add_certificate.address.clone().into(); let listener = self .listeners @@ -1161,13 +1146,7 @@ impl HttpsProxy { &mut self, remove_certificate: RemoveCertificate, ) -> Result, ProxyError> { - let address = remove_certificate - .address - .parse::() - .map_err(|parse_error| ProxyError::SocketParse { - address: remove_certificate.address, - error: parse_error.to_string(), - })?; + let address = remove_certificate.address.into(); let fingerprint = Fingerprint( hex::decode(&remove_certificate.fingerprint) @@ -1193,13 +1172,7 @@ impl HttpsProxy { &mut self, replace_certificate: ReplaceCertificate, ) -> Result, ProxyError> { - let address = replace_certificate - .address - .parse::() - .map_err(|parse_error| ProxyError::SocketParse { - address: replace_certificate.address.clone(), - error: parse_error.to_string(), - })?; + let address = replace_certificate.address.clone().into(); let listener = self .listeners @@ -1266,13 +1239,10 @@ impl ProxyConfiguration for HttpsProxy { AcceptError::RegisterError })?; - let public_address: StdSocketAddr = owned - .config - .public_address - .clone() - .unwrap_or(owned.config.address.clone()) - .parse() - .map_err(|_| AcceptError::WrongSocketAddress)?; + let public_address: StdSocketAddr = match owned.config.public_address.clone() { + Some(pub_addr) => pub_addr.into(), + None => owned.config.address.clone().into(), + }; let session = Rc::new(RefCell::new(HttpsSession::new( owned.answers.clone(), @@ -1505,10 +1475,7 @@ pub mod testing { max_buffers: usize, buffer_size: usize, ) -> anyhow::Result<()> { - let address = config - .address - .parse() - .with_context(|| "Could not parse socket address")?; + let address = config.address.clone().into(); let ServerParts { event_loop, @@ -1566,9 +1533,9 @@ pub mod testing { mod tests { use super::*; - use std::{str::FromStr, sync::Arc}; + use std::sync::Arc; - use sozu_command::config::ListenerBuilder; + use sozu_command::{config::ListenerBuilder, proto::command::SocketAddress}; use crate::router::{trie::TrieNode, MethodRule, PathRule, Route, Router}; @@ -1624,8 +1591,7 @@ mod tests { &Route::ClusterId(cluster_id1) )); - let address: StdSocketAddr = FromStr::from_str("127.0.0.1:1032") - .expect("test address 127.0.0.1:1032 should be parsed"); + let address = SocketAddress::new_v4(127, 0, 0, 1, 1032); let resolver = Arc::new(MutexWrappedCertificateResolver::default()); let server_config = ServerConfig::builder_with_protocol_versions(&[ @@ -1637,13 +1603,13 @@ mod tests { let rustls_details = Arc::new(server_config); - let default_config = ListenerBuilder::new_https(address) + let default_config = ListenerBuilder::new_https(address.clone()) .to_tls(None) .expect("Could not create default HTTPS listener config"); let listener = HttpsListener { listener: None, - address, + address: address.into(), fronts, rustls_details, resolver, diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 12c8d7f9b..7d3768411 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -36,9 +36,10 @@ //! We need the `sozu_command_lib` to build a listener. //! //! ``` -//! use sozu_command_lib::config::ListenerBuilder; +//! use sozu_command_lib::{config::ListenerBuilder, proto::command::SocketAddress}; //! -//! let http_listener = ListenerBuilder::new_http("127.0.0.1:8080") +//! let address = SocketAddress::new_v4(127,0,0,1,8080); +//! let http_listener = ListenerBuilder::new_http(address) //! .to_http(None) //! .expect("Could not create HTTP listener"); //! ``` @@ -120,11 +121,11 @@ //! ``` //! use std::collections::BTreeMap; //! -//! use sozu_command_lib::proto::command::{PathRule, RequestHttpFrontend, RulePosition}; +//! use sozu_command_lib::proto::command::{PathRule, RequestHttpFrontend, RulePosition, SocketAddress}; //! //! let http_front = RequestHttpFrontend { //! cluster_id: Some("my-cluster".to_string()), -//! address: "127.0.0.1:8080".to_string(), +//! address: SocketAddress::new_v4(127,0,0,1,8080), //! hostname: "example.com".to_string(), //! path: PathRule::prefix(String::from("/")), //! position: RulePosition::Pre.into(), @@ -144,12 +145,12 @@ //! The `address` field must match the IP and port of the backend server. //! //! ``` -//! use sozu_command_lib::proto::command::{AddBackend, LoadBalancingParams}; +//! use sozu_command_lib::proto::command::{AddBackend, LoadBalancingParams, SocketAddress}; //! //! let http_backend = AddBackend { //! cluster_id: "my-cluster".to_string(), //! backend_id: "test-backend".to_string(), -//! address: "127.0.0.1:8000".to_string(), +//! address: SocketAddress::new_v4(127,0,0,1,8000), //! load_balancing_parameters: Some(LoadBalancingParams::default()), //! ..Default::default() //! }; @@ -226,7 +227,7 @@ //! logging::setup_logging, //! proto::command::{ //! request::RequestType, AddBackend, Cluster, LoadBalancingAlgorithms, LoadBalancingParams, -//! PathRule, Request, RequestHttpFrontend, RulePosition, +//! PathRule, Request, RequestHttpFrontend, RulePosition, SocketAddress, //! }, //! request::WorkerRequest, //! }; @@ -236,7 +237,7 @@ //! //! info!("starting up"); //! -//! let http_listener = ListenerBuilder::new_http("127.0.0.1:8080") +//! let http_listener = ListenerBuilder::new_http(SocketAddress::new_v4(127,0,0,1,8080)) //! .to_http(None) //! .expect("Could not create HTTP listener"); //! @@ -261,7 +262,7 @@ //! //! let http_front = RequestHttpFrontend { //! cluster_id: Some("my-cluster".to_string()), -//! address: "127.0.0.1:8080".to_string(), +//! address: SocketAddress::new_v4(127,0,0,1,8080), //! hostname: "example.com".to_string(), //! path: PathRule::prefix(String::from("/")), //! position: RulePosition::Pre.into(), @@ -274,7 +275,7 @@ //! let http_backend = AddBackend { //! cluster_id: "my-cluster".to_string(), //! backend_id: "test-backend".to_string(), -//! address: "127.0.0.1:8000".to_string(), +//! address: SocketAddress::new_v4(127,0,0,1,8000), //! load_balancing_parameters: Some(LoadBalancingParams::default()), //! ..Default::default() //! }; @@ -649,10 +650,8 @@ pub enum ListenerError { PemParse(String), #[error("failed to build rustls context, {0}")] BuildRustls(String), - #[error("Wrong socket address")] - SocketParse { address: String, error: String }, - #[error("could not activate listener with address {address}: {error}")] - Activation { address: String, error: String }, + #[error("could not activate listener with address {address:?}: {error}")] + Activation { address: SocketAddr, error: String }, #[error("Could not register listener socket: {0}")] SocketRegistration(std::io::Error), #[error("could not add frontend: {0}")] @@ -700,8 +699,6 @@ pub enum ProxyError { RemoveCertificate(ListenerError), #[error("could not replace certificate: {0}")] ReplaceCertificate(ListenerError), - #[error("Wrong address {address}: {error}")] - SocketParse { address: String, error: String }, #[error("wrong certificate fingerprint: {0}")] WrongCertificateFingerprint(String), #[error("this request is not supported by the proxy")] diff --git a/lib/src/protocol/kawa_h1/mod.rs b/lib/src/protocol/kawa_h1/mod.rs index 3d2387573..50eac5b2c 100644 --- a/lib/src/protocol/kawa_h1/mod.rs +++ b/lib/src/protocol/kawa_h1/mod.rs @@ -1409,7 +1409,7 @@ impl Http Http WorkerResponse { let new_backend = Backend::new( &add_backend.backend_id, - add_backend.address.parse().unwrap(), + add_backend.address.clone().into(), add_backend.sticky_id.clone(), add_backend.load_balancing_parameters.clone(), add_backend.backup, @@ -1111,7 +1111,7 @@ impl Server { } fn remove_backend(&mut self, req_id: &str, backend: &RemoveBackend) -> WorkerResponse { - let address = backend.address.parse().unwrap(); + let address = backend.address.clone().into(); self.backends .borrow_mut() .remove_backend(&backend.cluster_id, &address); @@ -1232,10 +1232,7 @@ impl Server { req_id, activate.proxy, activate ); - let address: std::net::SocketAddr = match activate.address.parse() { - Ok(a) => a, - Err(e) => return WorkerResponse::error(req_id, format!("Wrong socket address: {e}")), - }; + let address: std::net::SocketAddr = activate.address.clone().into(); match ListenerType::try_from(activate.proxy) { Ok(ListenerType::Http) => { @@ -1312,10 +1309,7 @@ impl Server { req_id, deactivate.proxy, deactivate ); - let address: std::net::SocketAddr = match deactivate.address.parse() { - Ok(a) => a, - Err(e) => return WorkerResponse::error(req_id, format!("Wrong socket address: {e}")), - }; + let address: std::net::SocketAddr = deactivate.address.clone().into(); match ListenerType::try_from(deactivate.proxy) { Ok(ListenerType::Http) => { diff --git a/lib/src/socket.rs b/lib/src/socket.rs index 9440fb054..25e278211 100644 --- a/lib/src/socket.rs +++ b/lib/src/socket.rs @@ -465,20 +465,9 @@ impl SocketHandler for FrontRustls { } } -pub fn server_bind(addr: String) -> Result { - let address = addr.parse::().map_err(|parse_error| { - ServerBindError::InvalidSocketAddress { - address: addr.clone(), - error: parse_error.to_string(), - } - })?; - - let sock = Socket::new( - Domain::for_address(address), - Type::STREAM, - Some(Protocol::TCP), - ) - .map_err(ServerBindError::SocketCreationError)?; +pub fn server_bind(addr: SocketAddr) -> Result { + let sock = Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP)) + .map_err(ServerBindError::SocketCreationError)?; // set so_reuseaddr, but only on unix (mirrors what libstd does) if cfg!(unix) { @@ -489,9 +478,8 @@ pub fn server_bind(addr: String) -> Result { sock.set_reuse_port(true) .map_err(ServerBindError::SetReusePort)?; - // bind the socket - let addr = address.into(); - sock.bind(&addr).map_err(ServerBindError::BindError)?; + sock.bind(&addr.into()) + .map_err(ServerBindError::BindError)?; sock.set_nonblocking(true) .map_err(ServerBindError::SetNonBlocking)?; diff --git a/lib/src/tcp.rs b/lib/src/tcp.rs index ff22be9dd..1323c412c 100644 --- a/lib/src/tcp.rs +++ b/lib/src/tcp.rs @@ -449,7 +449,7 @@ impl TcpSession { push_event(Event { kind: EventKind::BackendUp as i32, backend_id: Some(backend.backend_id.to_owned()), - address: Some(backend.address.to_string()), + address: Some(backend.address.into()), cluster_id: None, }); } @@ -499,7 +499,7 @@ impl TcpSession { push_event(Event { kind: EventKind::BackendDown as i32, backend_id: Some(backend.backend_id.to_owned()), - address: Some(backend.address.to_string()), + address: Some(backend.address.into()), cluster_id: None, }); } @@ -1032,19 +1032,11 @@ impl TcpListener { pool: Rc>, token: Token, ) -> Result { - let address = config - .address - .parse::() - .map_err(|parse_error| ListenerError::SocketParse { - address: config.address.clone(), - error: parse_error.to_string(), - })?; - Ok(TcpListener { cluster_id: None, listener: None, token, - address, + address: config.address.clone().into(), pool, config, active: false, @@ -1063,7 +1055,7 @@ impl TcpListener { } let mut listener = tcp_listener.or_else(|| { - server_bind(self.config.address.clone()) + server_bind(self.config.address.clone().into()) .map_err(|e| { error!("could not create listener {:?}: {}", self.config.address, e); }) @@ -1202,14 +1194,7 @@ impl TcpProxy { } pub fn add_tcp_front(&mut self, front: RequestTcpFrontend) -> Result<(), ProxyError> { - let address = - front - .address - .parse::() - .map_err(|parse_error| ProxyError::SocketParse { - address: front.address.clone(), - error: parse_error.to_string(), - })?; + let address = front.address.into(); let mut listener = self .listeners @@ -1220,20 +1205,13 @@ impl TcpProxy { self.fronts .insert(front.cluster_id.to_string(), listener.token); - listener.set_tags(front.address.to_string(), Some(front.tags)); + listener.set_tags(address.to_string(), Some(front.tags)); listener.cluster_id = Some(front.cluster_id); Ok(()) } pub fn remove_tcp_front(&mut self, front: RequestTcpFrontend) -> Result<(), ProxyError> { - let address = - front - .address - .parse::() - .map_err(|parse_error| ProxyError::SocketParse { - address: front.address.clone(), - error: parse_error.to_string(), - })?; + let address = front.address.into(); let mut listener = match self .listeners @@ -1244,7 +1222,7 @@ impl TcpProxy { None => return Err(ProxyError::NoListenerFound(address)), }; - listener.set_tags(front.address, None); + listener.set_tags(address.to_string(), None); if let Some(cluster_id) = listener.cluster_id.take() { self.fronts.remove(&cluster_id); } @@ -1325,16 +1303,7 @@ impl ProxyConfiguration for TcpProxy { WorkerResponse::ok(message.id) } RequestType::RemoveListener(remove) => { - let address = match remove.address.parse() { - Ok(a) => a, - Err(e) => { - return WorkerResponse::error( - message.id, - format!("Wrong socket address: {e}"), - ) - } - }; - if !self.remove_listener(address) { + if !self.remove_listener(remove.address.clone().into()) { WorkerResponse::error( message.id, format!("no TCP listener to remove at address {:?}", remove.address), @@ -1475,10 +1444,7 @@ pub mod testing { buffer_size: usize, channel: ProxyChannel, ) -> anyhow::Result<()> { - let address = config - .address - .parse() - .with_context(|| "Could not parse socket address")?; + let address = config.address.clone().into(); let ServerParts { event_loop, @@ -1537,6 +1503,7 @@ mod tests { use super::testing::start_tcp_worker; use crate::testing::*; + use sozu_command::proto::command::SocketAddress; use std::{ io::{Read, Write}, net::{Shutdown, TcpListener, TcpStream}, @@ -1673,7 +1640,7 @@ mod tests { /// used in tests only pub fn start_proxy() -> anyhow::Result> { - let config = ListenerBuilder::new_tcp("127.0.0.1:1234") + let config = ListenerBuilder::new_tcp(SocketAddress::new_v4(127, 0, 0, 1, 1234)) .to_tcp(None) .expect("could not create listener config"); @@ -1688,15 +1655,13 @@ mod tests { { let front = RequestTcpFrontend { cluster_id: String::from("yolo"), - address: "127.0.0.1:1234".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1234), ..Default::default() }; let backend = sozu_command_lib::response::Backend { cluster_id: String::from("yolo"), backend_id: String::from("yolo-0"), - address: "127.0.0.1:5678" - .parse() - .with_context(|| "Could not parse address")?, + address: SocketAddress::new_v4(127, 0, 0, 1, 5678).into(), load_balancing_parameters: Some(LoadBalancingParams::default()), sticky_id: None, backup: None, @@ -1718,15 +1683,13 @@ mod tests { { let front = RequestTcpFrontend { cluster_id: String::from("yolo"), - address: "127.0.0.1:1235".to_string(), + address: SocketAddress::new_v4(127, 0, 0, 1, 1235), ..Default::default() }; let backend = sozu_command::response::Backend { cluster_id: String::from("yolo"), backend_id: String::from("yolo-0"), - address: "127.0.0.1:5678" - .parse() - .with_context(|| "Could not parse address")?, + address: SocketAddress::new_v4(127, 0, 0, 1, 5678).into(), load_balancing_parameters: Some(LoadBalancingParams::default()), sticky_id: None, backup: None, diff --git a/lib/src/tls.rs b/lib/src/tls.rs index e6055d01f..e061c3d05 100644 --- a/lib/src/tls.rs +++ b/lib/src/tls.rs @@ -490,12 +490,12 @@ mod tests { use rand::{seq::SliceRandom, thread_rng}; use sozu_command::{ certificate::parse_pem, - proto::command::{AddCertificate, CertificateAndKey}, + proto::command::{AddCertificate, CertificateAndKey, SocketAddress}, }; #[test] fn lifecycle() -> Result<(), Box> { - let address = "127.0.0.1:8080".to_string(); + let address = SocketAddress::new_v4(127, 0, 0, 1, 8080); let mut resolver = CertificateResolver::default(); let certificate_and_key = CertificateAndKey { certificate: String::from(include_str!("../assets/certificate.pem")), @@ -531,7 +531,7 @@ mod tests { #[test] fn name_override() -> Result<(), Box> { - let address = "127.0.0.1:8080".to_string(); + let address = SocketAddress::new_v4(127, 0, 0, 1, 8080); let mut resolver = CertificateResolver::default(); let certificate_and_key = CertificateAndKey { certificate: String::from(include_str!("../assets/certificate.pem")), @@ -576,7 +576,7 @@ mod tests { #[test] fn replacement() -> Result<(), Box> { - let address = "127.0.0.1:8080".to_string(); + let address = SocketAddress::new_v4(127, 0, 0, 1, 8080); let mut resolver = CertificateResolver::default(); // --------------------------------------------------------------------- @@ -641,7 +641,7 @@ mod tests { #[test] fn expiration_override() -> Result<(), Box> { - let address = "127.0.0.1:8080".to_string(); + let address = SocketAddress::new_v4(127, 0, 0, 1, 8080); let mut resolver = CertificateResolver::default(); // --------------------------------------------------------------------- @@ -758,7 +758,7 @@ mod tests { // --------------------------------------------------------------------- // load certificates in resolver - let address = "127.0.0.1:8080".to_string(); + let address = SocketAddress::new_v4(127, 0, 0, 1, 8080); let mut resolver = CertificateResolver::default(); for certificate in &certificates {