sozu_command_lib/lib.rs
1//! Tools and types used to communicate with Sōzu.
2
3#[macro_use]
4extern crate serde;
5
6/// The floor each H2 listener knob must meet — the single list, expanded once
7/// per validator that enforces it (sozu-proxy/sozu#1418).
8///
9/// Expands `$callback!($config, <field>, <minimum>)` once per knob, in a fixed
10/// order, so the five doors into a listener configuration share one list
11/// instead of five copies of it: `ListenerBuilder::validate_h2_thresholds`
12/// (`crate::config`, the config file and `sozu ctl add listener`),
13/// `validate_h2_flood_knobs_http`/`_https` (`crate::state`,
14/// `UpdateHttp(s)Listener`) and `validate_h2_flood_knobs_http_listener`/
15/// `_https_listener` (`crate::state`, a raw protobuf
16/// `Add{Http,Https}Listener`). Each supplies its own one-knob callback because
17/// the error types differ — `ConfigError::H2ThresholdBelowMinimum` names the
18/// listener, `StateError::InvalidValue` names the field — but none supplies
19/// its own list. Adding a knob to one door and forgetting another is what
20/// reopens sozu#1418 one level up; with the list here it is not expressible.
21///
22/// `h2_graceful_shutdown_deadline_seconds` is deliberately absent: `0` there
23/// means "wait forever (no forced close after GOAWAY)".
24macro_rules! for_each_h2_knob_floor {
25 ($callback:ident, $config:ident) => {
26 $callback!($config, h2_max_rst_stream_per_window, 1);
27 $callback!($config, h2_max_ping_per_window, 1);
28 $callback!($config, h2_max_settings_per_window, 1);
29 $callback!($config, h2_max_empty_data_per_window, 1);
30 $callback!($config, h2_max_window_update_stream0_per_window, 1);
31 $callback!($config, h2_max_continuation_frames, 1);
32 $callback!($config, h2_max_glitch_count, 1);
33 $callback!($config, h2_max_rst_stream_lifetime, 1);
34 $callback!($config, h2_max_rst_stream_abusive_lifetime, 1);
35 $callback!($config, h2_max_rst_stream_emitted_lifetime, 1);
36 $callback!($config, h2_max_header_list_size, 1);
37 $callback!($config, h2_max_header_table_size, 1);
38 $callback!($config, h2_max_header_fields, 1);
39 $callback!($config, h2_max_concurrent_streams, 1);
40 // The runtime floor is 2 (`lib/src/protocol/mux/h2.rs`'s `.max(2)`);
41 // anything lower is silently promoted, so refuse it instead.
42 $callback!($config, h2_stream_shrink_ratio, 2);
43 };
44}
45pub(crate) use for_each_h2_knob_floor;
46
47#[macro_use]
48/// custom made logging macros
49pub mod logging;
50/// Custom buffer used for parsing within the Sōzu codebase.
51pub mod buffer;
52/// TLS certificates
53pub mod certificate;
54/// channels used for communication between main process and workers
55pub mod channel;
56/// parse TOML config and generate requests from it
57pub mod config;
58/// listener identity: socket address plus optional network interface
59pub mod listener_key;
60/// parse Requests
61pub mod parser;
62/// two-phase coordination of protected health-check headers
63pub mod protected_transaction;
64/// Contains Rust types generated by [`prost`](https://docs.rs/prost/latest/prost/)
65/// using the protobuf definition in `command.proto`.
66///
67/// The two main types are `Request` and `Response`.
68///
69/// Because these types were originally defined in Rust, and later adapted for protobuf,
70/// the Rust translation of the protobuf definition looks a bit weird. Instead of having
71/// `Request` being a simple enum with Payload like this:
72///
73/// ```ignore
74/// pub enum Request {
75/// SaveState(String),
76/// LoadState(String),
77/// // ...
78/// }
79/// ```
80///
81/// It is defined with `oneof` in protobuf. and looks like this in Rust:
82///
83/// ```ignore
84/// pub struct Request {
85/// pub request_type: ::core::option::Option<request::RequestType>,
86/// }
87///
88/// pub mod request {
89/// pub enum RequestType {
90/// #[prost(string, tag = "1")]
91/// SaveState(::prost::alloc::string::String),
92/// /// load a state file, given its path
93/// #[prost(string, tag = "2")]
94/// LoadState(::prost::alloc::string::String),
95/// }
96/// }
97/// ```
98///
99/// but can be instantiated this way:
100///
101/// ```ignore
102/// let load_state_request: Request = RequestType::LoadState(path).into();
103/// ```
104///
105/// A bit cumbersome, but it is the only way to benefit from protobuf in Rust.
106pub mod proto;
107/// File descriptor readiness
108pub mod ready;
109/// Helper functions around types received by Sōzu
110pub mod request;
111/// Helper functions around types sent by Sōzu
112pub mod response;
113/// sockets used to pass file descriptors
114pub mod scm_socket;
115/// systemd `sd_notify` integration (READY=1 / STOPPING=1 / etc.)
116pub mod sd_notify;
117/// protected health-check header values and their keyed fingerprints
118pub mod secret;
119/// A representation of Sōzu's state
120pub mod state;
121/// A writer used for logging
122pub mod writer;
123
124/// Used only when returning errors
125#[derive(Debug)]
126pub enum ObjectKind {
127 Backend,
128 Certificate,
129 Cluster,
130 HttpFrontend,
131 HttpsFrontend,
132 HttpListener,
133 HttpsListener,
134 Listener,
135 TcpCluster,
136 TcpListener,
137 TcpFrontend,
138 UdpListener,
139 UdpFrontend,
140}
141
142pub trait AsString {
143 fn as_string_or(&self, default: &'static str) -> String;
144}
145
146impl<T: ToString> AsString for Option<T> {
147 fn as_string_or(&self, default: &'static str) -> String {
148 match self {
149 None => default.to_string(),
150 Some(t) => t.to_string(),
151 }
152 }
153}
154
155pub trait AsStr {
156 fn as_str_or(&self, default: &'static str) -> &str;
157}
158
159impl<T: AsRef<str>> AsStr for Option<T> {
160 fn as_str_or(&self, default: &'static str) -> &str {
161 match self {
162 None => default,
163 Some(s) => s.as_ref(),
164 }
165 }
166}