1use std::path::PathBuf;
6
7use crate::core::config::Config;
8
9use super::{
10 config::{ServerConfig, ServerEndpoint, ServerUserToken, ANONYMOUS_USER_TOKEN_ID},
11 constants,
12 server::Server,
13};
14
15const DEFAULT_ENDPOINT_PATH: &str = "/";
16
17pub struct ServerBuilder {
23 config: ServerConfig,
24}
25
26impl ServerBuilder {
27 pub fn new() -> Self {
28 Self {
29 config: ServerConfig::default(),
30 }
31 }
32
33 pub fn from_config(config: ServerConfig) -> Self {
35 Self { config }
36 }
37
38 pub fn new_anonymous<T>(application_name: T) -> Self
40 where
41 T: Into<String>,
42 {
43 let user_token_ids = vec![ANONYMOUS_USER_TOKEN_ID.to_string()];
44 Self::new()
45 .application_name(application_name)
46 .endpoint(
47 "none",
48 ServerEndpoint::new_none(DEFAULT_ENDPOINT_PATH, &user_token_ids),
49 )
50 .discovery_urls(vec![DEFAULT_ENDPOINT_PATH.into()])
51 }
52
53 pub fn new_sample() -> Self {
56 warn!("Sample configuration is for testing purposes only. Use a proper configuration in your production environment");
57
58 let path = DEFAULT_ENDPOINT_PATH;
59
60 let user_token_ids = [
61 "sample_password_user",
62 "sample_x509_user",
63 ANONYMOUS_USER_TOKEN_ID,
64 ]
65 .iter()
66 .map(|u| u.to_string())
67 .collect::<Vec<String>>();
68
69 Self::new()
70 .application_name("OPC UA Sample Server")
71 .application_uri("urn:OPC UA Sample Server")
72 .product_uri("urn:OPC UA Sample Server Testkit")
73 .create_sample_keypair(true)
74 .certificate_path("own/cert.der")
75 .private_key_path("private/private.pem")
76 .pki_dir("./pki")
77 .discovery_server_url(Some(constants::DEFAULT_DISCOVERY_SERVER_URL.to_string()))
78 .user_token(
79 "sample_password_user",
80 ServerUserToken {
81 user: "sample1".to_string(),
82 pass: Some("sample1pwd".to_string()),
83 x509: None,
84 thumbprint: None,
85 },
86 )
87 .user_token(
88 "sample_x509_user",
89 ServerUserToken {
90 user: "sample_x509".to_string(),
91 pass: None,
92 x509: Some("./users/sample-x509.der".to_string()),
93 thumbprint: None,
94 },
95 )
96 .user_token(
97 "unused_user",
98 ServerUserToken {
99 user: "unused".to_string(),
100 pass: Some("unused1".to_string()),
101 x509: None,
102 thumbprint: None,
103 },
104 )
105 .endpoints(vec![
106 ("none", ServerEndpoint::new_none(path, &user_token_ids)),
107 (
108 "basic128rsa15_sign",
109 ServerEndpoint::new_basic128rsa15_sign(path, &user_token_ids),
110 ),
111 (
112 "basic128rsa15_sign_encrypt",
113 ServerEndpoint::new_basic128rsa15_sign_encrypt(path, &user_token_ids),
114 ),
115 (
116 "aes128-sha256-rsaoaep_sign",
117 ServerEndpoint::new_aes128_sha256_rsaoaep_sign(path, &user_token_ids),
118 ),
119 (
120 "aes128-sha256-rsaoaep_sign_encrypt",
121 ServerEndpoint::new_aes128_sha256_rsaoaep_sign_encrypt(path, &user_token_ids),
122 ),
123 (
124 "aes256-sha256-rsapss_sign",
125 ServerEndpoint::new_aes256_sha256_rsapss_sign(path, &user_token_ids),
126 ),
127 (
128 "aes256-sha256-rsapss_sign_encrypt",
129 ServerEndpoint::new_aes256_sha256_rsapss_sign_encrypt(path, &user_token_ids),
130 ),
131 (
132 "basic256_sign",
133 ServerEndpoint::new_basic256_sign(path, &user_token_ids),
134 ),
135 (
136 "basic256_sign_encrypt",
137 ServerEndpoint::new_basic256_sign_encrypt(path, &user_token_ids),
138 ),
139 (
140 "basic256sha256_sign",
141 ServerEndpoint::new_basic256sha256_sign(path, &user_token_ids),
142 ),
143 (
144 "basic256sha256_sign_encrypt",
145 ServerEndpoint::new_basic256sha256_sign_encrypt(path, &user_token_ids),
146 ),
147 ("no_access", ServerEndpoint::new_none("/noaccess", &[])),
148 ])
149 .discovery_urls(vec![DEFAULT_ENDPOINT_PATH.into()])
150 }
151
152 pub fn server(self) -> Option<Server> {
157 if self.is_valid() {
158 Some(Server::new(self.config()))
159 } else {
160 None
161 }
162 }
163
164 pub fn config(self) -> ServerConfig {
168 self.config
169 }
170
171 pub fn is_valid(&self) -> bool {
173 self.config.is_valid()
174 }
175
176 pub fn application_name<T>(mut self, application_name: T) -> Self
178 where
179 T: Into<String>,
180 {
181 self.config.application_name = application_name.into();
182 self
183 }
184
185 pub fn application_uri<T>(mut self, application_uri: T) -> Self
187 where
188 T: Into<String>,
189 {
190 self.config.application_uri = application_uri.into();
191 self
192 }
193
194 pub fn product_uri<T>(mut self, product_uri: T) -> Self
196 where
197 T: Into<String>,
198 {
199 self.config.product_uri = product_uri.into();
200 self
201 }
202
203 pub fn create_sample_keypair(mut self, create_sample_keypair: bool) -> Self {
206 self.config.create_sample_keypair = create_sample_keypair;
207 self
208 }
209
210 pub fn certificate_path<T>(mut self, certificate_path: T) -> Self
214 where
215 T: Into<PathBuf>,
216 {
217 self.config.certificate_path = Some(certificate_path.into());
218 self
219 }
220
221 pub fn private_key_path<T>(mut self, private_key_path: T) -> Self
225 where
226 T: Into<PathBuf>,
227 {
228 self.config.private_key_path = Some(private_key_path.into());
229 self
230 }
231
232 pub fn pki_dir<T>(mut self, pki_dir: T) -> Self
235 where
236 T: Into<PathBuf>,
237 {
238 self.config.pki_dir = pki_dir.into();
239 self
240 }
241
242 pub fn endpoint<T>(mut self, endpoint_id: T, endpoint: ServerEndpoint) -> Self
244 where
245 T: Into<String>,
246 {
247 self.config.endpoints.insert(endpoint_id.into(), endpoint);
248 self
249 }
250
251 pub fn endpoints<T>(mut self, endpoints: Vec<(T, ServerEndpoint)>) -> Self
253 where
254 T: Into<String>,
255 {
256 for e in endpoints {
257 self.config.endpoints.insert(e.0.into(), e.1);
258 }
259 self
260 }
261
262 pub fn user_token<T>(mut self, user_token_id: T, user_token: ServerUserToken) -> Self
264 where
265 T: Into<String>,
266 {
267 self.config
268 .user_tokens
269 .insert(user_token_id.into(), user_token);
270 self
271 }
272
273 pub fn discovery_server_url(mut self, discovery_server_url: Option<String>) -> Self {
275 self.config.discovery_server_url = discovery_server_url;
276 self
277 }
278
279 pub fn host_and_port<T>(mut self, host: T, port: u16) -> Self
281 where
282 T: Into<String>,
283 {
284 self.config.tcp_config.host = host.into();
285 self.config.tcp_config.port = port;
286 self
287 }
288
289 pub fn discovery_urls(mut self, discovery_urls: Vec<String>) -> Self {
293 self.config.discovery_urls = discovery_urls
294 .iter()
295 .map(|discovery_url| {
296 if discovery_url.starts_with('/') {
297 format!(
299 "opc.tcp://{}:{}/",
300 self.config.tcp_config.host, self.config.tcp_config.port
301 )
302 } else {
303 discovery_url.clone()
304 }
305 })
306 .collect();
307 self
308 }
309
310 pub fn max_subscriptions(mut self, max_subscriptions: usize) -> Self {
312 self.config.limits.max_subscriptions = max_subscriptions;
313 self
314 }
315
316 pub fn max_monitored_items_per_sub(mut self, max_monitored_items_per_sub: usize) -> Self {
318 self.config.limits.max_monitored_items_per_sub = max_monitored_items_per_sub;
319 self
320 }
321
322 pub fn max_array_length(mut self, max_array_length: usize) -> Self {
324 self.config.limits.max_array_length = max_array_length;
325 self
326 }
327
328 pub fn max_string_length(mut self, max_string_length: usize) -> Self {
331 self.config.limits.max_string_length = max_string_length;
332 self
333 }
334
335 pub fn max_byte_string_length(mut self, max_byte_string_length: usize) -> Self {
337 self.config.limits.max_byte_string_length = max_byte_string_length;
338 self
339 }
340
341 pub fn max_message_size(mut self, max_message_size: usize) -> Self {
343 self.config.limits.max_message_size = max_message_size;
344 self
345 }
346
347 pub fn max_chunk_count(mut self, max_chunk_count: usize) -> Self {
349 self.config.limits.max_chunk_count = max_chunk_count;
350 self
351 }
352
353 pub fn send_buffer_size(mut self, send_buffer_size: usize) -> Self {
355 self.config.limits.send_buffer_size = send_buffer_size;
356 self
357 }
358
359 pub fn receive_buffer_size(mut self, receive_buffer_size: usize) -> Self {
361 self.config.limits.receive_buffer_size = receive_buffer_size;
362 self
363 }
364
365 pub fn trust_client_certs(mut self) -> Self {
368 self.config.certificate_validation.trust_client_certs = true;
369 self
370 }
371
372 pub fn clients_can_modify_address_space(mut self) -> Self {
375 self.config.limits.clients_can_modify_address_space = true;
376 self
377 }
378
379 pub fn single_threaded_executor(mut self) -> Self {
382 self.config.performance.single_threaded_executor = true;
383 self
384 }
385
386 pub fn multi_threaded_executor(mut self) -> Self {
388 self.config.performance.single_threaded_executor = false;
389 self
390 }
391}