Branch data Line data Source code
1 : : /*
2 : : * Copyright 2025 Jinwoo Sung
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #pragma once
18 : :
19 : : #include <cstdint>
20 : : #include <string>
21 : :
22 : : #include "wirestead/base/constants.hpp"
23 : : #include "wirestead/util/input_validator.hpp"
24 : :
25 : : namespace wirestead {
26 : : namespace config {
27 : :
28 : : /**
29 : : * @brief Configuration for UDS Client
30 : : */
31 : : struct UdsClientConfig {
32 : : std::string socket_path = "/tmp/wirestead.sock";
33 : : unsigned retry_interval_ms = base::constants::DEFAULT_RETRY_INTERVAL_MS;
34 : : unsigned connection_timeout_ms = base::constants::DEFAULT_CONNECTION_TIMEOUT_MS;
35 : : int max_retries = base::constants::DEFAULT_MAX_RETRIES;
36 : : size_t backpressure_threshold = base::constants::DEFAULT_BACKPRESSURE_THRESHOLD;
37 : : base::constants::BackpressureStrategy backpressure_strategy = base::constants::BackpressureStrategy::Reliable;
38 : : bool enable_memory_pool = true;
39 : : // Size of the per-connection userspace read buffer that each
40 : : // async_read_some() fills. Raising this reduces read completions and
41 : : // callback dispatches on bulk transfers, at the cost of that much memory
42 : : // per connection.
43 : : size_t read_buffer_size = base::constants::DEFAULT_READ_BUFFER_SIZE;
44 : :
45 : 147 : UdsClientConfig() = default;
46 : :
47 : 48 : bool is_valid() const {
48 : 95 : return read_buffer_size >= base::constants::MIN_READ_BUFFER_SIZE &&
49 [ + + ]: 47 : read_buffer_size <= base::constants::MAX_READ_BUFFER_SIZE &&
50 [ + + ]: 46 : util::InputValidator::is_valid_uds_path(socket_path) &&
51 [ + + ]: 44 : retry_interval_ms >= base::constants::MIN_RETRY_INTERVAL_MS &&
52 [ + + ]: 43 : retry_interval_ms <= base::constants::MAX_RETRY_INTERVAL_MS &&
53 [ + + ]: 42 : connection_timeout_ms >= base::constants::MIN_CONNECTION_TIMEOUT_MS &&
54 [ + - ]: 41 : connection_timeout_ms <= base::constants::MAX_CONNECTION_TIMEOUT_MS &&
55 [ + + ]: 41 : backpressure_threshold >= base::constants::MIN_BACKPRESSURE_THRESHOLD &&
56 [ + + + + ]: 134 : backpressure_threshold <= base::constants::MAX_BACKPRESSURE_THRESHOLD &&
57 [ + + + + : 87 : (max_retries == -1 || (max_retries >= 0 && max_retries <= base::constants::MAX_RETRIES_LIMIT));
+ - ]
58 : : }
59 : :
60 : 45 : void validate_and_clamp() {
61 [ + + ]: 45 : if (read_buffer_size < base::constants::MIN_READ_BUFFER_SIZE) {
62 : 1 : read_buffer_size = base::constants::MIN_READ_BUFFER_SIZE;
63 [ + + ]: 44 : } else if (read_buffer_size > base::constants::MAX_READ_BUFFER_SIZE) {
64 : 1 : read_buffer_size = base::constants::MAX_READ_BUFFER_SIZE;
65 : : }
66 [ + + ]: 45 : if (retry_interval_ms < base::constants::MIN_RETRY_INTERVAL_MS) {
67 : 2 : retry_interval_ms = base::constants::MIN_RETRY_INTERVAL_MS;
68 [ + + ]: 43 : } else if (retry_interval_ms > base::constants::MAX_RETRY_INTERVAL_MS) {
69 : 1 : retry_interval_ms = base::constants::MAX_RETRY_INTERVAL_MS;
70 : : }
71 : :
72 [ + + ]: 45 : if (connection_timeout_ms < base::constants::MIN_CONNECTION_TIMEOUT_MS) {
73 : 1 : connection_timeout_ms = base::constants::MIN_CONNECTION_TIMEOUT_MS;
74 [ - + ]: 44 : } else if (connection_timeout_ms > base::constants::MAX_CONNECTION_TIMEOUT_MS) {
75 : 0 : connection_timeout_ms = base::constants::MAX_CONNECTION_TIMEOUT_MS;
76 : : }
77 : :
78 [ + + ]: 45 : if (backpressure_threshold < base::constants::MIN_BACKPRESSURE_THRESHOLD) {
79 : 1 : backpressure_threshold = base::constants::MIN_BACKPRESSURE_THRESHOLD;
80 [ + + ]: 44 : } else if (backpressure_threshold > base::constants::MAX_BACKPRESSURE_THRESHOLD) {
81 : 1 : backpressure_threshold = base::constants::MAX_BACKPRESSURE_THRESHOLD;
82 : : }
83 : :
84 [ + + + + ]: 45 : if (max_retries != -1 && max_retries > base::constants::MAX_RETRIES_LIMIT) {
85 : 1 : max_retries = base::constants::MAX_RETRIES_LIMIT;
86 : : }
87 : 45 : }
88 : : };
89 : :
90 : : /**
91 : : * @brief Configuration for UDS Server
92 : : */
93 : : struct UdsServerConfig {
94 : : std::string socket_path = "/tmp/wirestead.sock";
95 : : size_t backpressure_threshold = base::constants::DEFAULT_BACKPRESSURE_THRESHOLD;
96 : : base::constants::BackpressureStrategy backpressure_strategy = base::constants::BackpressureStrategy::Reliable;
97 : : bool enable_memory_pool = true;
98 : : // Size of the per-connection userspace read buffer that each
99 : : // async_read_some() fills. Raising this reduces read completions and
100 : : // callback dispatches on bulk transfers, at the cost of that much memory
101 : : // per connection.
102 : : size_t read_buffer_size = base::constants::DEFAULT_READ_BUFFER_SIZE;
103 : : // #437: 0 (unlimited) used to be the default, risking unbounded memory
104 : : // growth from a large number of slow/malicious clients. 0 still means
105 : : // unlimited for callers who explicitly opt into it.
106 : : int max_connections = static_cast<int>(base::constants::DEFAULT_MAX_CONNECTIONS);
107 : : int idle_timeout_ms = static_cast<int>(base::constants::DEFAULT_IDLE_TIMEOUT_MS); // 0 = disabled
108 : : // #438: POSIX file permission bits (e.g. 0660) applied to the socket file
109 : : // after bind, restricting which local users/groups can connect. -1 (the
110 : : // default) leaves the socket at whatever the process umask produces,
111 : : // matching prior behavior. Ignored on Windows.
112 : : int socket_permissions = -1;
113 : :
114 : 44 : bool is_valid() const {
115 : 87 : return read_buffer_size >= base::constants::MIN_READ_BUFFER_SIZE &&
116 [ + + ]: 43 : read_buffer_size <= base::constants::MAX_READ_BUFFER_SIZE &&
117 [ + + ]: 42 : util::InputValidator::is_valid_uds_path(socket_path) &&
118 [ + + ]: 40 : backpressure_threshold >= base::constants::MIN_BACKPRESSURE_THRESHOLD &&
119 [ + + + + ]: 39 : backpressure_threshold <= base::constants::MAX_BACKPRESSURE_THRESHOLD && max_connections >= 0 &&
120 [ + + + + ]: 37 : (idle_timeout_ms == 0 || (idle_timeout_ms >= static_cast<int>(base::constants::MIN_IDLE_TIMEOUT_MS) &&
121 [ + + + + ]: 89 : idle_timeout_ms <= static_cast<int>(base::constants::MAX_IDLE_TIMEOUT_MS))) &&
122 [ + + + - : 79 : (socket_permissions == -1 || (socket_permissions >= 0 && socket_permissions <= 0777));
+ - ]
123 : : }
124 : :
125 : 40 : void validate_and_clamp() {
126 [ + + ]: 40 : if (read_buffer_size < base::constants::MIN_READ_BUFFER_SIZE) {
127 : 1 : read_buffer_size = base::constants::MIN_READ_BUFFER_SIZE;
128 [ + + ]: 39 : } else if (read_buffer_size > base::constants::MAX_READ_BUFFER_SIZE) {
129 : 1 : read_buffer_size = base::constants::MAX_READ_BUFFER_SIZE;
130 : : }
131 [ + + ]: 40 : if (backpressure_threshold < base::constants::MIN_BACKPRESSURE_THRESHOLD) {
132 : 1 : backpressure_threshold = base::constants::MIN_BACKPRESSURE_THRESHOLD;
133 [ + + ]: 39 : } else if (backpressure_threshold > base::constants::MAX_BACKPRESSURE_THRESHOLD) {
134 : 1 : backpressure_threshold = base::constants::MAX_BACKPRESSURE_THRESHOLD;
135 : : }
136 : :
137 [ + + ]: 40 : if (max_connections < 0) {
138 : 1 : max_connections = 0;
139 [ + + ]: 39 : } else if (max_connections > static_cast<int>(base::constants::MAX_MAX_CONNECTIONS)) {
140 : 1 : max_connections = static_cast<int>(base::constants::MAX_MAX_CONNECTIONS);
141 : : }
142 : :
143 [ + + ]: 40 : if (idle_timeout_ms < 0) {
144 : 1 : idle_timeout_ms = 0;
145 [ + + ]: 39 : } else if (idle_timeout_ms != 0) {
146 [ - + ]: 3 : if (idle_timeout_ms < static_cast<int>(base::constants::MIN_IDLE_TIMEOUT_MS)) {
147 : 0 : idle_timeout_ms = static_cast<int>(base::constants::MIN_IDLE_TIMEOUT_MS);
148 [ + + ]: 3 : } else if (idle_timeout_ms > static_cast<int>(base::constants::MAX_IDLE_TIMEOUT_MS)) {
149 : 1 : idle_timeout_ms = static_cast<int>(base::constants::MAX_IDLE_TIMEOUT_MS);
150 : : }
151 : : }
152 : :
153 [ + + + - : 40 : if (socket_permissions != -1 && (socket_permissions < 0 || socket_permissions > 0777)) {
- + ]
154 : 0 : socket_permissions = -1;
155 : : }
156 : 40 : }
157 : : };
158 : :
159 : : } // namespace config
160 : : } // namespace wirestead
|