1use std::path::PathBuf;
6
7use opcua_core::config::Config;
8
9use crate::{
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: u32) -> 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: u32) -> 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: u32) -> 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: u32) -> 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: u32) -> Self {
337 self.config.limits.max_byte_string_length = max_byte_string_length;
338 self
339 }
340
341 pub fn trust_client_certs(mut self) -> Self {
344 self.config.certificate_validation.trust_client_certs = true;
345 self
346 }
347
348 pub fn clients_can_modify_address_space(mut self) -> Self {
351 self.config.limits.clients_can_modify_address_space = true;
352 self
353 }
354
355 pub fn single_threaded_executor(mut self) -> Self {
358 self.config.performance.single_threaded_executor = true;
359 self
360 }
361
362 pub fn multi_threaded_executor(mut self) -> Self {
364 self.config.performance.single_threaded_executor = false;
365 self
366 }
367}