1use std::{path::PathBuf, sync::Arc};
2
3use tokio_util::sync::CancellationToken;
4use tracing::warn;
5
6use crate::{constants, node_manager::TypeTreeForUser};
7use opcua_core::config::Config;
8use opcua_crypto::SecurityPolicy;
9use opcua_types::{BuildInfo, MessageSecurityMode, TypeLoader, TypeLoaderCollection};
10
11use super::{
12 authenticator::AuthManager, node_manager::NodeManagerBuilder, Limits, Server, ServerConfig,
13 ServerEndpoint, ServerHandle, ServerUserToken, ANONYMOUS_USER_TOKEN_ID,
14};
15
16pub struct ServerBuilder {
20 pub(crate) config: ServerConfig,
21 pub(crate) node_managers: Vec<Box<dyn NodeManagerBuilder>>,
22 pub(crate) authenticator: Option<Arc<dyn AuthManager>>,
23 pub(crate) type_tree_getter: Option<Arc<dyn TypeTreeForUser>>,
24 pub(crate) type_loaders: TypeLoaderCollection,
25 pub(crate) token: CancellationToken,
26 pub(crate) build_info: BuildInfo,
27}
28
29impl Default for ServerBuilder {
30 fn default() -> Self {
31 let builder = Self {
32 config: Default::default(),
33 node_managers: Default::default(),
34 authenticator: None,
35 token: CancellationToken::new(),
36 type_tree_getter: None,
37 build_info: BuildInfo::default(),
38 type_loaders: TypeLoaderCollection::new(),
39 };
40 #[cfg(feature = "generated-address-space")]
41 {
42 builder
43 .with_node_manager(
44 super::node_manager::memory::InMemoryNodeManagerBuilder::new(
45 super::node_manager::memory::CoreNodeManagerBuilder,
46 ),
47 )
48 .with_node_manager(super::diagnostics::DiagnosticsNodeManagerBuilder)
49 }
50 #[cfg(not(feature = "generated-address-space"))]
51 builder
52 }
53}
54
55impl ServerBuilder {
56 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn from_config(config: ServerConfig) -> Self {
66 Self {
67 config,
68 ..Default::default()
69 }
70 }
71
72 pub fn new_anonymous(application_name: impl Into<String>) -> Self {
74 Self::new()
75 .application_name(application_name)
76 .add_endpoint(
77 "none",
78 ServerEndpoint::new_none("/", &[ANONYMOUS_USER_TOKEN_ID.to_string()]),
79 )
80 .discovery_urls(vec!["/".to_owned()])
81 }
82
83 pub fn new_sample() -> Self {
86 warn!("Sample configuration is for testing purposes only. Use a proper configuration in your production environment");
87
88 let user_token_ids = vec![
89 ANONYMOUS_USER_TOKEN_ID,
90 "sample_password_user",
91 "sample_x509_user",
92 ];
93 let endpoint_path = "/";
94 Self::new()
95 .application_name("OPC UA Sample Server")
96 .application_uri("urn:OPC UA Sample Server")
97 .product_uri("urn:OPC UA Sample Server Testkit")
98 .create_sample_keypair(true)
99 .certificate_path("own/cert.der")
100 .private_key_path("private/private.pem")
101 .pki_dir("./pki")
102 .discovery_server_url(constants::DEFAULT_DISCOVERY_SERVER_URL)
103 .add_user_token(
104 "sample_password_user",
105 ServerUserToken {
106 user: "sample1".to_string(),
107 pass: Some("sample1pwd".to_string()),
108 ..Default::default()
109 },
110 )
111 .add_user_token(
112 "sample_x509_user",
113 ServerUserToken {
114 user: "sample_x509".to_string(),
115 x509: Some("./users/sample-x509.der".to_string()),
116 ..Default::default()
117 },
118 )
119 .add_endpoint(
120 "none",
121 (
122 endpoint_path,
123 SecurityPolicy::None,
124 MessageSecurityMode::None,
125 &user_token_ids as &[&str],
126 ),
127 )
128 .add_endpoint(
129 "basic128rsa15_sign",
130 (
131 endpoint_path,
132 SecurityPolicy::Basic128Rsa15,
133 MessageSecurityMode::Sign,
134 &user_token_ids as &[&str],
135 ),
136 )
137 .add_endpoint(
138 "basic128rsa15_sign_encrypt",
139 (
140 endpoint_path,
141 SecurityPolicy::Basic128Rsa15,
142 MessageSecurityMode::SignAndEncrypt,
143 &user_token_ids as &[&str],
144 ),
145 )
146 .add_endpoint(
147 "basic256_sign",
148 (
149 endpoint_path,
150 SecurityPolicy::Basic256,
151 MessageSecurityMode::Sign,
152 &user_token_ids as &[&str],
153 ),
154 )
155 .add_endpoint(
156 "basic256_sign_encrypt",
157 (
158 endpoint_path,
159 SecurityPolicy::Basic256,
160 MessageSecurityMode::SignAndEncrypt,
161 &user_token_ids as &[&str],
162 ),
163 )
164 .add_endpoint(
165 "basic256sha256_sign",
166 (
167 endpoint_path,
168 SecurityPolicy::Basic256Sha256,
169 MessageSecurityMode::Sign,
170 &user_token_ids as &[&str],
171 ),
172 )
173 .add_endpoint(
174 "basic256sha256_sign_encrypt",
175 (
176 endpoint_path,
177 SecurityPolicy::Basic256Sha256,
178 MessageSecurityMode::SignAndEncrypt,
179 &user_token_ids as &[&str],
180 ),
181 )
182 .add_endpoint(
183 "endpoint_aes128sha256rsaoaep_sign",
184 (
185 endpoint_path,
186 SecurityPolicy::Aes128Sha256RsaOaep,
187 MessageSecurityMode::Sign,
188 &user_token_ids as &[&str],
189 ),
190 )
191 .add_endpoint(
192 "endpoint_aes128sha256rsaoaep_sign_encrypt",
193 (
194 endpoint_path,
195 SecurityPolicy::Aes128Sha256RsaOaep,
196 MessageSecurityMode::SignAndEncrypt,
197 &user_token_ids as &[&str],
198 ),
199 )
200 .add_endpoint(
201 "endpoint_aes256sha256rsapss_sign",
202 (
203 endpoint_path,
204 SecurityPolicy::Aes256Sha256RsaPss,
205 MessageSecurityMode::Sign,
206 &user_token_ids as &[&str],
207 ),
208 )
209 .add_endpoint(
210 "endpoint_aes256sha256rsapss_sign_encrypt",
211 (
212 endpoint_path,
213 SecurityPolicy::Aes256Sha256RsaPss,
214 MessageSecurityMode::SignAndEncrypt,
215 &user_token_ids as &[&str],
216 ),
217 )
218 }
219
220 pub fn config(&self) -> &ServerConfig {
222 &self.config
223 }
224
225 pub fn with_config_from(mut self, path: impl Into<PathBuf>) -> Self {
230 self.config = ServerConfig::load(&path.into()).expect("Failed to load config");
231 self
232 }
233
234 pub fn with_config(mut self, config: ServerConfig) -> Self {
236 self.config = config;
237 self
238 }
239
240 pub fn config_mut(&mut self) -> &mut ServerConfig {
242 &mut self.config
243 }
244
245 pub fn limits_mut(&mut self) -> &mut Limits {
247 &mut self.config.limits
248 }
249
250 pub fn with_node_manager(mut self, node_manager: impl NodeManagerBuilder + 'static) -> Self {
255 self.node_managers.push(Box::new(node_manager));
256 self
257 }
258
259 pub fn without_node_managers(mut self) -> Self {
264 self.node_managers.clear();
265 self
266 }
267
268 pub fn with_authenticator(mut self, authenticator: Arc<dyn AuthManager>) -> Self {
270 self.authenticator = Some(authenticator);
271 self
272 }
273
274 pub fn with_type_tree_getter(mut self, type_tree_getter: Arc<dyn TypeTreeForUser>) -> Self {
286 self.type_tree_getter = Some(type_tree_getter);
287 self
288 }
289
290 pub fn build_info(mut self, build_info: BuildInfo) -> Self {
293 self.build_info = build_info;
294 self
295 }
296
297 pub fn application_name(mut self, application_name: impl Into<String>) -> Self {
299 self.config.application_name = application_name.into();
300 self
301 }
302
303 pub fn application_uri(mut self, application_uri: impl Into<String>) -> Self {
305 self.config.application_uri = application_uri.into();
306 self
307 }
308
309 pub fn product_uri(mut self, product_uri: impl Into<String>) -> Self {
311 self.config.product_uri = product_uri.into();
312 self
313 }
314
315 pub fn create_sample_keypair(mut self, create_sample_keypair: bool) -> Self {
317 self.config.create_sample_keypair = create_sample_keypair;
318 self
319 }
320
321 pub fn certificate_path(mut self, certificate_path: impl Into<PathBuf>) -> Self {
323 self.config.certificate_path = Some(certificate_path.into());
324 self
325 }
326
327 pub fn private_key_path(mut self, private_key_path: impl Into<PathBuf>) -> Self {
329 self.config.private_key_path = Some(private_key_path.into());
330 self
331 }
332
333 pub fn trust_client_certs(mut self, trust_client_certs: bool) -> Self {
336 self.config.certificate_validation.trust_client_certs = trust_client_certs;
337 self
338 }
339
340 pub fn check_cert_time(mut self, check_cert_time: bool) -> Self {
342 self.config.certificate_validation.check_time = check_cert_time;
343 self
344 }
345
346 pub fn pki_dir(mut self, pki_dir: impl Into<PathBuf>) -> Self {
348 self.config.pki_dir = pki_dir.into();
349 self
350 }
351
352 pub fn discovery_server_url(mut self, url: impl Into<String>) -> Self {
355 self.config.discovery_server_url = Some(url.into());
356 self
357 }
358
359 pub fn hello_timeout(mut self, timeout: u32) -> Self {
363 self.config.tcp_config.hello_timeout = timeout;
364 self
365 }
366
367 pub fn host(mut self, host: impl Into<String>) -> Self {
369 self.config.tcp_config.host = host.into();
370 self
371 }
372
373 pub fn port(mut self, port: u16) -> Self {
375 self.config.tcp_config.port = port;
376 self
377 }
378
379 pub fn limits(mut self, limits: Limits) -> Self {
381 self.config.limits = limits;
382 self
383 }
384
385 pub fn locale_ids(mut self, locale_ids: Vec<String>) -> Self {
387 self.config.locale_ids = locale_ids;
388 self
389 }
390
391 pub fn add_user_token(mut self, key: impl Into<String>, token: ServerUserToken) -> Self {
394 self.config.user_tokens.insert(key.into(), token);
395 self
396 }
397
398 pub fn discovery_urls(mut self, discovery_urls: Vec<String>) -> Self {
401 self.config.discovery_urls = discovery_urls;
402 self
403 }
404
405 pub fn default_endpoint(mut self, endpoint_id: impl Into<String>) -> Self {
407 self.config.default_endpoint = Some(endpoint_id.into());
408 self
409 }
410
411 pub fn add_endpoint(
413 mut self,
414 id: impl Into<String>,
415 endpoint: impl Into<ServerEndpoint>,
416 ) -> Self {
417 self.config.endpoints.insert(id.into(), endpoint.into());
418 self
419 }
420
421 pub fn subscription_poll_interval_ms(mut self, interval: u64) -> Self {
423 self.config.subscription_poll_interval_ms = interval;
424 self
425 }
426
427 pub fn publish_timeout_default_ms(mut self, timeout: u64) -> Self {
429 self.config.publish_timeout_default_ms = timeout;
430 self
431 }
432
433 pub fn max_timeout_ms(mut self, timeout: u32) -> Self {
440 self.config.max_timeout_ms = timeout;
441 self
442 }
443
444 pub fn max_secure_channel_token_lifetime_ms(mut self, lifetime: u32) -> Self {
449 self.config.max_secure_channel_token_lifetime_ms = lifetime;
450 self
451 }
452
453 pub fn build(self) -> Result<(Server, ServerHandle), String> {
456 Server::new_from_builder(self)
457 }
458
459 pub fn max_array_length(mut self, max_array_length: usize) -> Self {
461 self.config.limits.max_array_length = max_array_length;
462 self
463 }
464
465 pub fn max_string_length(mut self, max_string_length: usize) -> Self {
467 self.config.limits.max_string_length = max_string_length;
468 self
469 }
470
471 pub fn max_byte_string_length(mut self, max_byte_string_length: usize) -> Self {
473 self.config.limits.max_byte_string_length = max_byte_string_length;
474 self
475 }
476
477 pub fn max_message_size(mut self, max_message_size: usize) -> Self {
479 self.config.limits.max_message_size = max_message_size;
480 self
481 }
482
483 pub fn max_chunk_count(mut self, max_chunk_count: usize) -> Self {
485 self.config.limits.max_chunk_count = max_chunk_count;
486 self
487 }
488
489 pub fn send_buffer_size(mut self, send_buffer_size: usize) -> Self {
491 self.config.limits.send_buffer_size = send_buffer_size;
492 self
493 }
494
495 pub fn receive_buffer_size(mut self, receive_buffer_size: usize) -> Self {
497 self.config.limits.receive_buffer_size = receive_buffer_size;
498 self
499 }
500
501 pub fn max_browse_continuation_points(mut self, max_browse_continuation_points: usize) -> Self {
503 self.config.limits.max_browse_continuation_points = max_browse_continuation_points;
504 self
505 }
506
507 pub fn max_history_continuation_points(
509 mut self,
510 max_history_continuation_points: usize,
511 ) -> Self {
512 self.config.limits.max_history_continuation_points = max_history_continuation_points;
513 self
514 }
515
516 pub fn max_query_continuation_points(mut self, max_query_continuation_points: usize) -> Self {
518 self.config.limits.max_query_continuation_points = max_query_continuation_points;
519 self
520 }
521
522 pub fn max_sessions(mut self, max_sessions: usize) -> Self {
524 self.config.limits.max_sessions = max_sessions;
525 self
526 }
527
528 pub fn max_session_timeout_ms(mut self, max_session_timeout_ms: u64) -> Self {
531 self.config.max_session_timeout_ms = max_session_timeout_ms;
532 self
533 }
534
535 pub fn token(mut self, token: CancellationToken) -> Self {
540 self.token = token;
541 self
542 }
543
544 pub fn with_type_loader(mut self, loader: Arc<dyn TypeLoader>) -> Self {
549 self.type_loaders.add(loader);
550 self
551 }
552
553 pub fn diagnostics_enabled(mut self, enabled: bool) -> Self {
556 self.config.diagnostics = enabled;
557 self
558 }
559}