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 : : #include "wirestead/builder/uds_builder.hpp"
18 : :
19 : : #include <boost/asio/io_context.hpp>
20 : :
21 : : #include "wirestead/base/constants.hpp"
22 : : #include "wirestead/builder/auto_initializer.hpp"
23 : : #include "wirestead/config/validation.hpp"
24 : : #include "wirestead/diagnostics/exceptions.hpp"
25 : : #include "wirestead/util/input_validator.hpp"
26 : :
27 : : namespace wirestead {
28 : : namespace builder {
29 : :
30 : : // UdsClientBuilder implementation
31 : :
32 : 24 : UdsClientBuilder::UdsClientBuilder(const std::string& socket_path)
33 : 24 : : socket_path_(socket_path),
34 : 24 : auto_start_(false),
35 : 24 : independent_context_(false),
36 : 24 : retry_interval_(base::constants::DEFAULT_RETRY_INTERVAL_MS),
37 : 24 : max_retries_(base::constants::DEFAULT_MAX_RETRIES),
38 : 24 : connection_timeout_(base::constants::DEFAULT_CONNECTION_TIMEOUT_MS),
39 : 48 : read_buffer_size_(base::constants::DEFAULT_READ_BUFFER_SIZE) {
40 [ + + + - : 30 : if (socket_path.empty()) throw diagnostics::BuilderException("Socket path cannot be empty");
+ - + - +
- ]
41 : :
42 : : // Ensure background IO service is running
43 : 23 : AutoInitializer::ensure_io_context_running();
44 : 25 : }
45 : :
46 : 23 : std::unique_ptr<wrapper::UdsClient> UdsClientBuilder::build() {
47 : 23 : std::unique_ptr<wrapper::UdsClient> client;
48 [ + + ]: 23 : if (independent_context_) {
49 : 6 : client = std::make_unique<wrapper::UdsClient>(socket_path_, std::make_shared<boost::asio::io_context>());
50 : 6 : client->manage_external_context(true);
51 : : } else {
52 : 17 : client = std::make_unique<wrapper::UdsClient>(socket_path_);
53 : : }
54 : :
55 [ + + + - : 23 : if (this->on_data_) client->on_data(this->on_data_);
+ - ]
56 [ + + + - : 23 : if (this->on_data_batch_) client->on_data_batch(this->on_data_batch_);
+ - ]
57 [ + + + - : 23 : if (this->on_connect_) client->on_connect(this->on_connect_);
+ - ]
58 [ + + + - : 23 : if (this->on_disconnect_) client->on_disconnect(this->on_disconnect_);
+ - ]
59 [ + + + - : 23 : if (this->on_error_) client->on_error(this->on_error_);
+ - ]
60 [ + + + - : 23 : if (this->on_backpressure_) client->on_backpressure(this->on_backpressure_);
+ - ]
61 : :
62 [ + + + - ]: 23 : if (retry_interval_set_) client->retry_interval(retry_interval_);
63 [ + + + - ]: 23 : if (max_retries_set_) client->max_retries(max_retries_);
64 [ + + + - ]: 23 : if (connection_timeout_set_) client->connection_timeout(connection_timeout_);
65 [ - + - - ]: 23 : if (read_buffer_size_set_) client->read_buffer_size(read_buffer_size_);
66 : :
67 [ + + + - ]: 23 : if (this->bp_strategy_set_) client->backpressure_strategy(this->bp_strategy_);
68 : 23 : client->backpressure_threshold(this->get_effective_backpressure_threshold());
69 : :
70 [ + + ]: 23 : if (this->framer_factory_) {
71 : 3 : client->framer(this->framer_factory_());
72 : : }
73 [ + + ]: 23 : if (this->on_message_) {
74 : 2 : client->on_message(this->on_message_);
75 : : }
76 [ + + ]: 23 : if (this->on_message_batch_) {
77 : 1 : client->on_message_batch(this->on_message_batch_);
78 : : }
79 : :
80 [ - + ]: 23 : if (auto_start_) {
81 : 0 : client->auto_start(true);
82 : : }
83 : :
84 : 23 : return client;
85 : 0 : }
86 : :
87 : 4 : UdsClientBuilder& UdsClientBuilder::auto_start(bool auto_start) {
88 : 4 : auto_start_ = auto_start;
89 : 4 : return *this;
90 : : }
91 : :
92 : 3 : UdsClientBuilder& UdsClientBuilder::retry_interval(std::chrono::milliseconds interval) {
93 : 3 : config::detail::duration(interval, base::constants::MIN_RETRY_INTERVAL_MS, base::constants::MAX_RETRY_INTERVAL_MS,
94 : : false, "invalid retry_interval");
95 : 3 : retry_interval_ = interval;
96 : 3 : retry_interval_set_ = true;
97 : 3 : return *this;
98 : : }
99 : :
100 : 3 : UdsClientBuilder& UdsClientBuilder::max_retries(int max_retries) {
101 : 3 : config::detail::range(max_retries, -1, base::constants::MAX_RETRIES_LIMIT, "invalid retry limit");
102 : 3 : max_retries_ = max_retries;
103 : 3 : max_retries_set_ = true;
104 : 3 : return *this;
105 : : }
106 : :
107 : 3 : UdsClientBuilder& UdsClientBuilder::connection_timeout(std::chrono::milliseconds timeout) {
108 : 3 : config::detail::duration(timeout, base::constants::MIN_CONNECTION_TIMEOUT_MS,
109 : : base::constants::MAX_CONNECTION_TIMEOUT_MS, false, "invalid connection_timeout");
110 : 3 : connection_timeout_ = timeout;
111 : 3 : connection_timeout_set_ = true;
112 : 3 : return *this;
113 : : }
114 : :
115 : 0 : UdsClientBuilder& UdsClientBuilder::read_buffer_size(size_t bytes) {
116 : 0 : config::detail::range(bytes, base::constants::MIN_READ_BUFFER_SIZE, base::constants::MAX_READ_BUFFER_SIZE,
117 : : "invalid read_buffer_size");
118 : 0 : read_buffer_size_ = bytes;
119 : 0 : read_buffer_size_set_ = true;
120 : 0 : return *this;
121 : : }
122 : :
123 : 7 : UdsClientBuilder& UdsClientBuilder::independent_context(bool use_independent) {
124 : 7 : independent_context_ = use_independent;
125 : 7 : return *this;
126 : : }
127 : :
128 : : // UdsServerBuilder implementation
129 : :
130 : 21 : UdsServerBuilder::UdsServerBuilder(const std::string& socket_path)
131 : 21 : : socket_path_(socket_path),
132 : 21 : auto_start_(false),
133 : 21 : independent_context_(false),
134 : 21 : max_clients_(0),
135 : 21 : client_limit_enabled_(false),
136 : 21 : idle_timeout_(0),
137 : 21 : idle_timeout_set_(false),
138 : 21 : read_buffer_size_(base::constants::DEFAULT_READ_BUFFER_SIZE) {
139 [ + + + - : 27 : if (socket_path.empty()) throw diagnostics::BuilderException("Socket path cannot be empty");
+ - + - +
- ]
140 : :
141 : : // Ensure background IO service is running
142 : 20 : AutoInitializer::ensure_io_context_running();
143 : 22 : }
144 : :
145 : 19 : std::unique_ptr<wrapper::UdsServer> UdsServerBuilder::build() {
146 : 19 : std::unique_ptr<wrapper::UdsServer> server;
147 [ + + ]: 19 : if (independent_context_) {
148 : 5 : server = std::make_unique<wrapper::UdsServer>(socket_path_, std::make_shared<boost::asio::io_context>());
149 : 5 : server->manage_external_context(true);
150 : : } else {
151 : 14 : server = std::make_unique<wrapper::UdsServer>(socket_path_);
152 : : }
153 : :
154 [ + + + - : 19 : if (this->on_data_) server->on_data(this->on_data_);
+ - ]
155 [ + + + - : 19 : if (this->on_data_batch_) server->on_data_batch(this->on_data_batch_);
+ - ]
156 [ + + + - : 19 : if (this->on_connect_) server->on_connect(this->on_connect_);
+ - ]
157 [ + + + - : 19 : if (this->on_disconnect_) server->on_disconnect(this->on_disconnect_);
+ - ]
158 [ + + + - : 19 : if (this->on_error_) server->on_error(this->on_error_);
+ - ]
159 [ + + + - : 19 : if (this->on_backpressure_) server->on_backpressure(this->on_backpressure_);
+ - ]
160 : :
161 [ + + ]: 19 : if (client_limit_enabled_) {
162 : 5 : server->max_clients(max_clients_);
163 : : }
164 [ + + ]: 19 : if (idle_timeout_set_) {
165 : 3 : server->idle_timeout(idle_timeout_);
166 : : }
167 [ - + - - ]: 19 : if (read_buffer_size_set_) server->read_buffer_size(read_buffer_size_);
168 : :
169 [ + + + - ]: 19 : if (this->bp_strategy_set_) server->backpressure_strategy(this->bp_strategy_);
170 : 19 : server->backpressure_threshold(this->get_effective_backpressure_threshold());
171 : :
172 [ + + ]: 19 : if (this->framer_factory_) {
173 : : // Corrected: ServerInterface::framer expects FramerFactory std::function
174 : 4 : server->framer(this->framer_factory_);
175 : : }
176 [ + + ]: 19 : if (this->on_message_) {
177 : 3 : server->on_message(this->on_message_);
178 : : }
179 [ + + ]: 19 : if (this->on_message_batch_) {
180 : 1 : server->on_message_batch(this->on_message_batch_);
181 : : }
182 : :
183 [ - + ]: 19 : if (auto_start_) {
184 : 0 : server->auto_start(true);
185 : : }
186 : :
187 : 19 : return server;
188 : 0 : }
189 : :
190 : 4 : UdsServerBuilder& UdsServerBuilder::auto_start(bool auto_start) {
191 : 4 : auto_start_ = auto_start;
192 : 4 : return *this;
193 : : }
194 : :
195 : 6 : UdsServerBuilder& UdsServerBuilder::independent_context(bool use_independent) {
196 : 6 : independent_context_ = use_independent;
197 : 6 : return *this;
198 : : }
199 : :
200 : 3 : UdsServerBuilder& UdsServerBuilder::idle_timeout(std::chrono::milliseconds timeout) {
201 : 3 : config::detail::duration(timeout, base::constants::MIN_IDLE_TIMEOUT_MS, base::constants::MAX_IDLE_TIMEOUT_MS, true,
202 : : "invalid idle_timeout");
203 : 3 : idle_timeout_ = timeout;
204 : 3 : idle_timeout_set_ = true;
205 : 3 : return *this;
206 : : }
207 : :
208 : 0 : UdsServerBuilder& UdsServerBuilder::read_buffer_size(size_t bytes) {
209 : 0 : config::detail::range(bytes, base::constants::MIN_READ_BUFFER_SIZE, base::constants::MAX_READ_BUFFER_SIZE,
210 : : "invalid read_buffer_size");
211 : 0 : read_buffer_size_ = bytes;
212 : 0 : read_buffer_size_set_ = true;
213 : 0 : return *this;
214 : : }
215 : :
216 : 3 : UdsServerBuilder& UdsServerBuilder::max_clients(uint32_t max_clients) {
217 : 3 : config::detail::range(max_clients, 0, base::constants::MAX_MAX_CONNECTIONS, "invalid client limit");
218 : 3 : max_clients_ = max_clients;
219 : 3 : client_limit_enabled_ = true;
220 : 3 : return *this;
221 : : }
222 : :
223 : 1 : UdsServerBuilder& UdsServerBuilder::single_client() {
224 : 1 : max_clients_ = 1;
225 : 1 : client_limit_enabled_ = true;
226 : 1 : return *this;
227 : : }
228 : :
229 : 2 : UdsServerBuilder& UdsServerBuilder::multi_client(size_t max) {
230 [ + + ]: 2 : if (max == 0) {
231 : 7 : throw diagnostics::BuilderException("multi_client max must be greater than 0");
232 : : }
233 : 1 : max_clients_ = static_cast<uint32_t>(max);
234 : 1 : client_limit_enabled_ = true;
235 : 1 : return *this;
236 : : }
237 : :
238 : : // Explicit template instantiations
239 : :
240 : : } // namespace builder
241 : : } // namespace wirestead
|