blob: 1b9eba7364f9e1f519e6e89ebf62c7e4247b4c3b [file]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use crate::client_wrappers::client_wrapper::ClientWrapper;
use crate::clients::client::IggyClient;
use crate::http::http_client::HttpClient;
use crate::prelude::{
ClientError, HttpClientConfig, IggyDuration, QuicClientConfig, QuicClientReconnectionConfig,
TcpClientConfig, TcpClientReconnectionConfig, WebSocketClient,
};
use crate::quic::quic_client::QuicClient;
use crate::tcp::tcp_client::TcpClient;
use iggy_binary_protocol::Client;
use iggy_common::{
AutoLogin, Credentials, TransportProtocol, WebSocketClientConfig,
WebSocketClientReconnectionConfig, WebSocketConfig,
};
use std::str::FromStr;
use std::sync::Arc;
/// Configuration for the `ClientProvider`.
/// It consists of the following fields:
/// - `transport`: the transport protocol to use (TCP, QUIC, or HTTP).
/// - `http`: the optional configuration for the HTTP transport.
/// - `quic`: the optional configuration for the QUIC transport.
/// - `tcp`: the optional configuration for the TCP transport.
#[derive(Debug)]
pub struct ClientProviderConfig {
/// The transport protocol to use.
pub transport: TransportProtocol,
/// The optional configuration for the HTTP transport.
pub http: Option<Arc<HttpClientConfig>>,
/// The optional configuration for the QUIC transport.
pub quic: Option<Arc<QuicClientConfig>>,
/// The optional configuration for the TCP transport.
pub tcp: Option<Arc<TcpClientConfig>>,
/// The optional configuration for the WebSocket transport.
pub websocket: Option<Arc<WebSocketClientConfig>>,
}
impl Default for ClientProviderConfig {
fn default() -> ClientProviderConfig {
ClientProviderConfig {
transport: TransportProtocol::Tcp,
http: Some(Arc::new(HttpClientConfig::default())),
quic: Some(Arc::new(QuicClientConfig::default())),
tcp: Some(Arc::new(TcpClientConfig::default())),
websocket: Some(Arc::new(WebSocketClientConfig::default())),
}
}
}
impl ClientProviderConfig {
/// Create a new `ClientProviderConfig` from the provided `Args`.
pub fn from_args(args: crate::prelude::Args) -> Result<Self, ClientError> {
Self::from_args_set_autologin(args, true)
}
/// Create a new `ClientProviderConfig` from the provided `Args` with possibility to enable or disable
/// auto login option for TCP or QUIC protocols.
pub fn from_args_set_autologin(
args: crate::prelude::Args,
auto_login: bool,
) -> Result<Self, ClientError> {
let transport = TransportProtocol::from_str(&args.transport)
.map_err(|_| ClientError::InvalidTransport(args.transport.clone()))?;
let mut config = Self {
transport,
http: None,
quic: None,
tcp: None,
websocket: None,
};
match config.transport {
TransportProtocol::Quic => {
config.quic = Some(Arc::new(QuicClientConfig {
client_address: args.quic_client_address,
server_address: args.quic_server_address,
server_name: args.quic_server_name,
heartbeat_interval: IggyDuration::from_str(&args.quic_heartbeat_interval)
.unwrap(),
reconnection: QuicClientReconnectionConfig {
enabled: args.quic_reconnection_enabled,
max_retries: args.quic_reconnection_max_retries,
interval: IggyDuration::from_str(&args.quic_reconnection_interval).unwrap(),
reestablish_after: IggyDuration::from_str(
&args.quic_reconnection_reestablish_after,
)
.unwrap(),
},
auto_login: if auto_login {
AutoLogin::Enabled(Credentials::UsernamePassword(
args.username,
args.password,
))
} else {
AutoLogin::Disabled
},
response_buffer_size: args.quic_response_buffer_size,
max_concurrent_bidi_streams: args.quic_max_concurrent_bidi_streams,
datagram_send_buffer_size: args.quic_datagram_send_buffer_size,
initial_mtu: args.quic_initial_mtu,
send_window: args.quic_send_window,
receive_window: args.quic_receive_window,
keep_alive_interval: args.quic_keep_alive_interval,
max_idle_timeout: args.quic_max_idle_timeout,
validate_certificate: args.quic_validate_certificate,
}));
}
TransportProtocol::Http => {
config.http = Some(Arc::new(HttpClientConfig {
api_url: args.http_api_url,
retries: args.http_retries,
}));
}
TransportProtocol::Tcp => {
config.tcp = Some(Arc::new(TcpClientConfig {
server_address: args.tcp_server_address,
tls_enabled: args.tcp_tls_enabled,
tls_domain: args.tcp_tls_domain,
tls_ca_file: args.tcp_tls_ca_file,
tls_validate_certificate: true,
nodelay: args.tcp_nodelay,
heartbeat_interval: IggyDuration::from_str(&args.tcp_heartbeat_interval)
.unwrap(),
reconnection: TcpClientReconnectionConfig {
enabled: args.tcp_reconnection_enabled,
max_retries: args.tcp_reconnection_max_retries,
interval: IggyDuration::from_str(&args.tcp_reconnection_interval).unwrap(),
reestablish_after: IggyDuration::from_str(
&args.tcp_reconnection_reestablish_after,
)
.unwrap(),
},
auto_login: if auto_login {
AutoLogin::Enabled(Credentials::UsernamePassword(
args.username,
args.password,
))
} else {
AutoLogin::Disabled
},
}));
}
TransportProtocol::WebSocket => {
config.websocket = Some(Arc::new(WebSocketClientConfig {
server_address: args.websocket_server_address,
heartbeat_interval: IggyDuration::from_str(&args.websocket_heartbeat_interval)
.unwrap(),
reconnection: WebSocketClientReconnectionConfig {
enabled: args.websocket_reconnection_enabled,
max_retries: args.websocket_reconnection_max_retries,
interval: IggyDuration::from_str(&args.websocket_reconnection_interval)
.unwrap(),
reestablish_after: IggyDuration::from_str(
&args.websocket_reconnection_reestablish_after,
)
.unwrap(),
},
auto_login: if auto_login {
AutoLogin::Enabled(Credentials::UsernamePassword(
args.username,
args.password,
))
} else {
AutoLogin::Disabled
},
ws_config: WebSocketConfig::default(),
tls_enabled: args.websocket_tls_enabled,
tls_domain: args.websocket_tls_domain,
tls_ca_file: args.websocket_tls_ca_file,
tls_validate_certificate: args.websocket_tls_validate_certificate,
}));
}
}
Ok(config)
}
}
/// Create a default `IggyClient` with the default configuration.
pub async fn get_default_client_() -> Result<IggyClient, ClientError> {
get_client(Arc::new(ClientProviderConfig::default())).await
}
/// Create a `IggyClient` for the specific transport based on the provided configuration.
pub async fn get_client(config: Arc<ClientProviderConfig>) -> Result<IggyClient, ClientError> {
let client = get_raw_connected_client(config).await?;
Ok(IggyClient::builder().with_client(client).build()?)
}
/// Create a `Client` for the specific transport based on the provided configuration.
pub async fn get_raw_connected_client(
config: Arc<ClientProviderConfig>,
) -> Result<ClientWrapper, ClientError> {
get_raw_client(config, true).await
}
/// Create a `Client` for the specific transport based on the provided configuration.
pub async fn get_raw_client(
config: Arc<ClientProviderConfig>,
establish_connection: bool,
) -> Result<ClientWrapper, ClientError> {
match config.transport {
TransportProtocol::Quic => {
let quic_config = config.quic.as_ref().unwrap();
let client = QuicClient::create(quic_config.clone())?;
if establish_connection {
Client::connect(&client).await?
};
Ok(ClientWrapper::Quic(client))
}
TransportProtocol::Http => {
let http_config = config.http.as_ref().unwrap();
let client = HttpClient::create(http_config.clone())?;
Ok(ClientWrapper::Http(client))
}
TransportProtocol::Tcp => {
let tcp_config = config.tcp.as_ref().unwrap();
let client = TcpClient::create(tcp_config.clone())?;
if establish_connection {
Client::connect(&client).await?
};
Ok(ClientWrapper::Tcp(client))
}
TransportProtocol::WebSocket => {
let websocket_config = config.websocket.as_ref().unwrap();
let client = WebSocketClient::create(websocket_config.clone())?;
if establish_connection {
Client::connect(&client).await?
};
Ok(ClientWrapper::WebSocket(client))
}
}
}