1use std::time::Duration;
2
3use hopr_api::types::primitive::prelude::*;
4pub use hopr_transport::{
5 TagAllocatorConfig,
6 config::{
7 HoprPacketPipelineConfig, HoprProtocolConfig, HostConfig, HostType, ProbeConfig, SessionGlobalConfig,
8 TransportConfig, looks_like_domain,
9 },
10};
11use validator::{Validate, ValidationError};
12
13pub const DEFAULT_HOST: &str = "0.0.0.0";
14pub const DEFAULT_PORT: u16 = 9091;
15
16#[inline]
17fn default_invalid_address() -> Address {
18 Address::default()
19}
20
21#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_with::serde_as)]
22#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Validate)]
23#[cfg_attr(
24 feature = "serde",
25 derive(serde::Serialize, serde::Deserialize),
26 serde(deny_unknown_fields)
27)]
28pub struct SafeModule {
29 #[cfg_attr(
30 feature = "serde",
31 serde_as(as = "serde_with::DisplayFromStr"),
32 serde(default = "default_invalid_address")
33 )]
34 #[default(default_invalid_address())]
35 pub safe_address: Address,
36 #[cfg_attr(
37 feature = "serde",
38 serde_as(as = "serde_with::DisplayFromStr"),
39 serde(default = "default_invalid_address")
40 )]
41 #[default(default_invalid_address())]
42 pub module_address: Address,
43}
44
45#[allow(dead_code)]
46fn validate_directory_exists(s: &str) -> Result<(), ValidationError> {
47 if std::path::Path::new(s).is_dir() {
48 Ok(())
49 } else {
50 Err(ValidationError::new("Invalid directory path specified"))
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Validate)]
55#[cfg_attr(
56 feature = "serde",
57 derive(serde::Serialize, serde::Deserialize),
58 serde(deny_unknown_fields)
59)]
60pub struct HoprLibConfig {
61 #[validate(nested)]
63 #[default(default_host())]
64 #[cfg_attr(feature = "serde", serde(default = "default_host"))]
65 pub host: HostConfig,
66 #[cfg_attr(feature = "serde", serde(default))]
68 pub publish: bool,
69 #[validate(nested)]
71 #[cfg_attr(feature = "serde", serde(default))]
72 pub protocol: HoprProtocolConfig,
73 #[validate(nested)]
75 #[cfg_attr(feature = "serde", serde(default))]
76 pub safe_module: SafeModule,
77 #[default(default_out_index_sync_period())]
85 #[validate(custom(function = "validate_out_index_sync_period"))]
86 #[cfg_attr(
87 feature = "serde",
88 serde(default = "default_out_index_sync_period", with = "humantime_serde")
89 )]
90 pub out_index_sync_period: Duration,
91}
92
93const MINIMUM_OUT_SYNC_PERIOD: Duration = Duration::from_secs(1);
94
95fn validate_out_index_sync_period(lifetime: &Duration) -> Result<(), ValidationError> {
96 if lifetime < &MINIMUM_OUT_SYNC_PERIOD {
97 Err(ValidationError::new("out_index_sync_period is too low"))
98 } else {
99 Ok(())
100 }
101}
102
103fn default_out_index_sync_period() -> Duration {
104 Duration::from_secs(15)
105}
106
107#[inline]
110fn default_host() -> HostConfig {
111 HostConfig {
112 address: HostType::IPv4(DEFAULT_HOST.to_owned()),
113 port: DEFAULT_PORT,
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 #[cfg(feature = "serde")]
120 #[test]
121 fn test_config_should_be_serializable_using_serde() -> Result<(), Box<dyn std::error::Error>> {
122 let cfg = super::HoprLibConfig::default();
123
124 let yaml = serde_saphyr::to_string(&cfg)?;
125 let cfg_after_serde: super::HoprLibConfig = serde_saphyr::from_str(&yaml)?;
126 assert_eq!(cfg, cfg_after_serde);
127
128 Ok(())
129 }
130}