ombrac_server/config/
cli.rs1use std::net::SocketAddr;
2use std::path::PathBuf;
3
4use clap::Parser;
5use clap::builder::Styles;
6use clap::builder::styling::{AnsiColor, Style};
7
8use ombrac_transport::quic::Congestion;
9
10use crate::config::{TlsMode, TransportConfig};
11
12#[derive(Parser, Debug)]
14#[command(version, about, long_about = None, styles = styles())]
15pub struct Args {
16 #[clap(long, short = 'c', value_name = "FILE")]
18 pub config: Option<PathBuf>,
19
20 #[clap(
22 long,
23 short = 'k',
24 help_heading = "Required",
25 value_name = "STR",
26 required_unless_present = "config"
27 )]
28 pub secret: Option<String>,
29
30 #[clap(
32 long,
33 short = 'l',
34 help_heading = "Required",
35 value_name = "ADDR",
36 required_unless_present = "config"
37 )]
38 pub listen: Option<SocketAddr>,
39
40 #[clap(flatten)]
41 pub transport: CliTransportConfig,
42
43 #[cfg(feature = "tracing")]
44 #[clap(flatten)]
45 pub logging: CliLoggingConfig,
46}
47
48#[derive(Parser, Debug, Clone)]
50pub struct CliTransportConfig {
51 #[clap(long, value_enum, help_heading = "Transport")]
53 pub tls_mode: Option<TlsMode>,
54
55 #[clap(long, help_heading = "Transport", value_name = "FILE")]
58 pub ca_cert: Option<PathBuf>,
59
60 #[clap(long, help_heading = "Transport", value_name = "FILE")]
62 pub tls_cert: Option<PathBuf>,
63
64 #[clap(long, help_heading = "Transport", value_name = "FILE")]
66 pub tls_key: Option<PathBuf>,
67
68 #[clap(long, help_heading = "Transport", value_name = "BOOL")]
70 pub zero_rtt: Option<bool>,
71
72 #[clap(
74 long,
75 help_heading = "Transport",
76 value_name = "PROTOCOLS",
77 value_delimiter = ','
78 )]
79 pub alpn_protocols: Option<Vec<Vec<u8>>>,
80
81 #[clap(long, help_heading = "Transport", value_name = "ALGORITHM")]
83 pub congestion: Option<Congestion>,
84
85 #[clap(long, help_heading = "Transport", value_name = "NUM")]
87 pub cwnd_init: Option<u64>,
88
89 #[clap(long, help_heading = "Transport", value_name = "TIME")]
91 pub idle_timeout: Option<u64>,
92
93 #[clap(long, help_heading = "Transport", value_name = "TIME")]
95 pub keep_alive: Option<u64>,
96
97 #[clap(long, help_heading = "Transport", value_name = "NUM")]
99 pub max_streams: Option<u64>,
100}
101
102#[cfg(feature = "tracing")]
104#[derive(Parser, Debug, Clone)]
105pub struct CliLoggingConfig {
106 #[clap(long, help_heading = "Logging", value_name = "LEVEL")]
108 pub log_level: Option<String>,
109}
110
111impl CliTransportConfig {
112 pub fn into_transport_config(self) -> TransportConfig {
114 TransportConfig {
115 tls_mode: self.tls_mode,
116 ca_cert: self.ca_cert,
117 tls_cert: self.tls_cert,
118 tls_key: self.tls_key,
119 zero_rtt: self.zero_rtt,
120 alpn_protocols: self.alpn_protocols,
121 congestion: self.congestion,
122 cwnd_init: self.cwnd_init,
123 idle_timeout: self.idle_timeout,
124 keep_alive: self.keep_alive,
125 max_streams: self.max_streams,
126 }
127 }
128}
129
130#[cfg(feature = "tracing")]
131impl CliLoggingConfig {
132 pub fn into_logging_config(self) -> crate::config::LoggingConfig {
134 crate::config::LoggingConfig {
135 log_level: self.log_level,
136 }
137 }
138}
139
140#[derive(Debug)]
142pub struct CliConfig {
143 pub secret: Option<String>,
144 pub listen: Option<SocketAddr>,
145 pub transport: TransportConfig,
146 #[cfg(feature = "tracing")]
147 pub logging: crate::config::LoggingConfig,
148}
149
150impl Args {
151 pub fn parse_to_config() -> CliConfig {
153 let args = Self::parse();
154 CliConfig {
155 secret: args.secret,
156 listen: args.listen,
157 transport: args.transport.into_transport_config(),
158 #[cfg(feature = "tracing")]
159 logging: args.logging.into_logging_config(),
160 }
161 }
162
163 pub fn config_path() -> Option<PathBuf> {
165 Self::parse().config
166 }
167}
168
169fn styles() -> Styles {
170 Styles::styled()
171 .header(Style::new().bold().fg_color(Some(AnsiColor::Green.into())))
172 .usage(Style::new().bold().fg_color(Some(AnsiColor::Green.into())))
173 .literal(Style::new().bold().fg_color(Some(AnsiColor::Cyan.into())))
174 .placeholder(Style::new().fg_color(Some(AnsiColor::Cyan.into())))
175 .valid(Style::new().bold().fg_color(Some(AnsiColor::Cyan.into())))
176 .invalid(Style::new().bold().fg_color(Some(AnsiColor::Yellow.into())))
177 .error(Style::new().bold().fg_color(Some(AnsiColor::Red.into())))
178}