1#![allow(dead_code)]
2use std::{
3 net::SocketAddr,
4 path::PathBuf,
5};
6
7use derive_builder::Builder;
8
9use dfx_base::fields::converters::datetime::DateTimeFormat;
10use native_tls::{TlsAcceptor, TlsConnector};
11use crate::{
12 connection::SocketSettings,
13 session::SessionSchedule,
14};
15
16use dfx_base::session_id::SessionId;
17
18use super::{SessionSettingsError, SettingOption};
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub(crate) enum ConnectionType {
22 Acceptor,
23 Initiator,
24}
25
26impl TryFrom<&str> for ConnectionType {
27 type Error = SessionSettingsError;
28
29 fn try_from(value: &str) -> Result<Self, Self::Error> {
30 match value {
31 "initiator" => Ok(Self::Initiator),
32 "acceptor" => Ok(Self::Acceptor),
33 e => Err(SessionSettingsError::InvalidValue {
34 setting: SettingOption::ConnectionType.into(),
35 value: e.into(),
36 }),
37 }
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub(crate) enum SettingsConnection {
43 Acceptor {
44 is_dynamic: bool,
45 session_qualifier: Option<String>,
46 accept_addr: SocketAddr,
47 logon_timeout: u32,
48 logout_timeout: u32,
49 },
50 Initiator {
51 connect_addr: SocketAddr,
52
53 reconnect_interval: u32,
55 heart_bt_int: u32,
56 logon_timeout: u32,
57 logout_timeout: u32,
58 },
59}
60
61impl SettingsConnection {
62 #[must_use]
66 pub(crate) fn is_initiator(&self) -> bool {
67 matches!(self, Self::Initiator { .. })
68 }
69
70 #[must_use]
74 pub(crate) fn is_acceptor(&self) -> bool {
75 matches!(self, Self::Acceptor { .. })
76 }
77
78 pub(crate) fn socket_addr(&self) -> &SocketAddr {
79 match self {
80 SettingsConnection::Acceptor { accept_addr, .. } => accept_addr,
81 SettingsConnection::Initiator { connect_addr, .. } => connect_addr,
82 }
83 }
84
85 pub(crate) fn heart_bt_int(&self) -> Option<u32> {
86 match self {
87 SettingsConnection::Acceptor { .. } => None,
88 SettingsConnection::Initiator { heart_bt_int, .. } => Some(*heart_bt_int),
89 }
90 }
91
92 pub(crate) fn logon_timeout(&self) -> u32 {
93 match self {
94 SettingsConnection::Acceptor { logon_timeout, .. } => *logon_timeout,
95 SettingsConnection::Initiator { logon_timeout, .. } => *logon_timeout,
96 }
97 }
98
99 pub(crate) fn logout_timeout(&self) -> u32 {
100 match self {
101 SettingsConnection::Acceptor { logout_timeout, .. } => *logout_timeout,
102 SettingsConnection::Initiator { logout_timeout, .. } => *logout_timeout,
103 }
104 }
105}
106
107#[derive(Builder, Clone, Debug, PartialEq, Eq)]
108pub(crate) struct SocketOptions {
109 no_delay: bool,
110 send_buffer_size: usize,
111 receive_buffer_size: usize,
112 send_timeout: u64,
113 receive_timeout: u64,
114}
115
116impl SocketOptions {
117
118 pub(crate) fn builder() -> SocketOptionsBuilder {
119 SocketOptionsBuilder::create_empty()
120 }
121
122 pub(crate) fn no_delay(&self) -> bool {
123 self.no_delay
124 }
125
126 pub(crate) fn send_timeout(&self) -> u64 {
135 self.send_timeout
136 }
137
138 pub(crate) fn receive_timeout(&self) -> u64 {
139 self.receive_timeout
140 }
141}
142
143#[derive(Clone)]
144pub(crate) enum SslOptions {
145 Acceptor { acceptor: TlsAcceptor },
146 Initiator { initiator: TlsConnector, domain: String }
147}
148
149impl std::fmt::Debug for SslOptions {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 match self {
152 Self::Acceptor { acceptor: _ } => f.debug_struct("Acceptor").finish(),
153 Self::Initiator { initiator, domain } => f.debug_struct("Initiator").field("initiator", initiator).field("domain", domain).finish(),
154 }
155 }
156}
157
158#[derive(Builder, Clone, Debug, PartialEq, Eq)]
159pub struct LoggingOptions {
160 file_log_path: Option<String>,
161 debug_file_log_path: Option<String>,
162}
163
164impl LoggingOptions {
165 pub(crate) fn builder() -> LoggingOptionsBuilder {
166 LoggingOptionsBuilder::create_empty()
167 }
168
169 pub(crate) fn file_log_path(&self) -> Option<&String> {
170 self.file_log_path.as_ref()
171 }
172
173 pub(crate) fn debug_file_log_path(&self) -> Option<&String> {
174 self.debug_file_log_path.as_ref()
175 }
176}
177
178#[derive(Clone, Debug, PartialEq, Eq)]
179pub(crate) enum Persistence {
180 FileStore { path: PathBuf },
181 Memory,
182 None,
183}
184
185#[derive(Builder, Clone, Debug, PartialEq, Eq)]
186pub(crate) struct ValidationOptions {
187 milliseconds_in_time_stamp: bool,
188 refresh_on_logon: bool,
189 reset_on_logon: bool,
190 reset_on_logout: bool,
191 reset_on_disconnect: bool,
192 send_redundant_resend_requests: bool,
193 resend_session_level_rejects: bool,
194 time_stamp_precision: DateTimeFormat,
195 enable_last_msg_seq_num_processed: bool,
196 max_messages_in_resend_request: u32,
197 send_logout_before_disconnect_from_timeout: bool,
198 ignore_poss_dup_resend_requests: bool,
199 requires_orig_sending_time: bool,
200
201 use_data_dictionary: bool,
203 data_dictionary: Option<String>,
204 transport_data_dictionary: Option<String>,
205 app_data_dictionary: Option<String>,
206 validate_fields_out_of_order: bool,
207 validate_fields_have_values: bool,
208 validate_user_defined_fields: bool,
209 validate_length_and_checksum: bool,
210 allow_unknown_msg_fields: bool,
211 check_latency: bool,
212 max_latency: u32,
213}
214
215impl ValidationOptions {
216 pub(crate) fn builder() -> ValidationOptionsBuilder {
217 ValidationOptionsBuilder::create_empty()
218 }
219
220 pub(crate) fn milliseconds_in_time_stamp(&self) -> bool {
221 self.milliseconds_in_time_stamp
222 }
223
224 pub(crate) fn refresh_on_logon(&self) -> bool {
225 self.refresh_on_logon
226 }
227
228 pub(crate) fn reset_on_logon(&self) -> bool {
229 self.reset_on_logon
230 }
231
232 pub(crate) fn reset_on_logout(&self) -> bool {
233 self.reset_on_logout
234 }
235
236 pub(crate) fn reset_on_disconnect(&self) -> bool {
237 self.reset_on_disconnect
238 }
239
240 pub(crate) fn send_redundant_resend_requests(&self) -> bool {
241 self.send_redundant_resend_requests
242 }
243
244 pub(crate) fn resend_session_level_rejects(&self) -> bool {
245 self.resend_session_level_rejects
246 }
247
248 pub(crate) fn time_stamp_precision(&self) -> &DateTimeFormat {
249 &self.time_stamp_precision
250 }
251
252 pub(crate) fn enable_last_msg_seq_num_processed(&self) -> bool {
253 self.enable_last_msg_seq_num_processed
254 }
255
256 pub(crate) fn max_messages_in_resend_request(&self) -> u32 {
257 self.max_messages_in_resend_request
258 }
259
260 pub(crate) fn send_logout_before_disconnect_from_timeout(&self) -> bool {
261 self.send_logout_before_disconnect_from_timeout
262 }
263
264 pub(crate) fn ignore_poss_dup_resend_requests(&self) -> bool {
265 self.ignore_poss_dup_resend_requests
266 }
267
268 pub(crate) fn requires_orig_sending_time(&self) -> bool {
269 self.requires_orig_sending_time
270 }
271
272 pub(crate) fn use_data_dictionary(&self) -> bool {
273 self.use_data_dictionary
274 }
275
276 pub(crate) fn data_dictionary(&self) -> Option<&String> {
277 self.data_dictionary.as_ref()
278 }
279
280 pub(crate) fn transport_data_dictionary(&self) -> Option<&String> {
281 self.transport_data_dictionary.as_ref()
282 }
283
284 pub(crate) fn app_data_dictionary(&self) -> Option<&String> {
285 self.app_data_dictionary.as_ref()
286 }
287
288 pub(crate) fn validate_fields_out_of_order(&self) -> bool {
289 self.validate_fields_out_of_order
290 }
291
292 pub(crate) fn validate_fields_have_values(&self) -> bool {
293 self.validate_fields_have_values
294 }
295
296 pub(crate) fn validate_user_defined_fields(&self) -> bool {
297 self.validate_user_defined_fields
298 }
299
300 pub(crate) fn validate_length_and_checksum(&self) -> bool {
301 self.validate_length_and_checksum
302 }
303
304 pub(crate) fn allow_unknown_msg_fields(&self) -> bool {
305 self.allow_unknown_msg_fields
306 }
307
308 pub(crate) fn check_latency(&self) -> bool {
309 self.check_latency
310 }
311
312 pub(crate) fn max_latency(&self) -> u32 {
313 self.max_latency
314 }
315}
316
317#[derive(Builder, Clone, Debug)]
318pub(crate) struct SessionSetting {
319 session_id: SessionId,
320 connection: SettingsConnection,
321 socket_options: SocketOptions,
322 ssl_options: Option<SslOptions>,
323 logging: LoggingOptions,
324 persistence: Persistence,
325 default_appl_ver_id: Option<String>,
326 schedule: SessionSchedule,
327 validation_options: ValidationOptions,
328}
329
330impl SessionSetting {
331 pub(crate) fn builder() -> SessionSettingBuilder {
332 SessionSettingBuilder::create_empty()
333 }
334
335 pub(crate) fn session_id(&self) -> &SessionId {
336 &self.session_id
337 }
338
339 pub(crate) fn connection(&self) -> &SettingsConnection {
340 &self.connection
341 }
342
343 pub(crate) fn socket_options(&self) -> &SocketOptions {
344 &self.socket_options
345 }
346
347 pub(crate) fn ssl_options(&self) -> Option<&SslOptions> {
348 self.ssl_options.as_ref()
349 }
350
351 pub(crate) fn logging(&self) -> &LoggingOptions {
352 &self.logging
353 }
354
355 pub(crate) fn persistence(&self) -> &Persistence {
356 &self.persistence
357 }
358
359 pub(crate) fn default_appl_ver_id(&self) -> Option<&String> {
360 self.default_appl_ver_id.as_ref()
361 }
362
363 pub(crate) fn schedule(&self) -> &SessionSchedule {
364 &self.schedule
365 }
366
367 pub(crate) fn validation_options(&self) -> &ValidationOptions {
368 &self.validation_options
369 }
370}
371
372#[derive(Debug, Clone, PartialEq, Eq)]
373pub(crate) struct SessionSettingOld {
374 pub(crate) connection_type: ConnectionType,
375 pub(crate) is_dynamic: bool,
376
377 pub(crate) begin_string: String,
378 pub(crate) sender_comp_id: String,
379 pub(crate) sender_sub_id: Option<String>,
380 pub(crate) sender_location_id: Option<String>,
381 pub(crate) target_comp_id: String,
382 pub(crate) target_sub_id: Option<String>,
383 pub(crate) target_location_id: Option<String>,
384
385 pub(crate) session_qualifier: Option<String>,
386 pub(crate) default_appl_ver_id: Option<String>,
387
388 pub(crate) non_stop_session: bool,
389 pub(crate) use_local_time: bool,
390 pub(crate) time_zone: Option<String>,
391 pub(crate) start_day: Option<String>,
392 pub(crate) end_day: Option<String>,
393 pub(crate) start_time: Option<String>,
394 pub(crate) end_time: Option<String>,
395
396 pub(crate) milliseconds_in_time_stamp: bool,
397 pub(crate) refresh_on_logon: bool,
398 pub(crate) reset_on_logon: bool,
399 pub(crate) reset_on_logout: bool,
400 pub(crate) reset_on_disconnect: bool,
401 pub(crate) send_redundant_resend_requests: bool,
402 pub(crate) resend_session_level_rejects: bool,
403 pub(crate) time_stamp_precision: Option<String>,
404 pub(crate) enable_last_msg_seq_num_processed: bool,
405 pub(crate) max_messages_in_resend_request: u32,
406 pub(crate) send_logout_before_disconnect_from_timeout: bool,
407 pub(crate) ignore_poss_dup_resend_requests: bool,
408 pub(crate) requires_orig_sending_time: bool,
409
410 pub(crate) use_data_dictionary: bool,
412 pub(crate) data_dictionary: Option<String>,
413 pub(crate) transport_data_dictionary: Option<String>,
414 pub(crate) app_data_dictionary: Option<String>,
415 pub(crate) validate_fields_out_of_order: bool,
416 pub(crate) validate_fields_have_values: bool,
417 pub(crate) validate_user_defined_fields: bool,
418 pub(crate) validate_length_and_checksum: bool,
419 pub(crate) allow_unknown_msg_fields: bool,
420 pub(crate) check_latency: bool,
421 pub(crate) max_latency: u32,
422
423 pub(crate) reconnect_interval: u32,
424 pub(crate) heart_bt_int: Option<u32>, pub(crate) logon_timeout: u32,
426 pub(crate) logout_timeout: u32,
427
428 pub(crate) socket_connect_host: Option<String>,
431 pub(crate) socket_connect_port: Option<u32>,
432 pub(crate) socket_accept_host: Option<String>,
439 pub(crate) socket_accept_port: Option<u32>,
440
441 pub(crate) persist_messages: bool,
443 pub(crate) file_store_path: Option<String>,
445
446 pub(crate) file_log_path: Option<String>,
448 pub(crate) debug_file_log_path: Option<String>,
449
450 pub(crate) socket_nodelay: bool,
452 pub(crate) socket_send_buffer_size: Option<String>,
453 pub(crate) socket_receive_buffer_size: Option<String>,
454 pub(crate) socket_send_timeout: Option<String>,
455 pub(crate) socket_receive_timeout: Option<String>,
456
457 pub(crate) ssl_enable: bool,
459 pub(crate) ssl_server_name: Option<String>,
460 pub(crate) ssl_protocols: Option<String>,
461 pub(crate) ssl_validate_certificates: Option<String>,
462 pub(crate) ssl_check_certificate_revocation: Option<String>,
463 pub(crate) ssl_certificate: Option<String>,
464 pub(crate) ssl_certificate_password: Option<String>,
465 pub(crate) ssl_require_client_certificate: Option<String>,
466 pub(crate) ssl_ca_certificate: Option<String>,
467}
468
469impl SessionSetting {
470 pub(crate) fn score(&self, session_id: &SessionId) -> u16 {
471 let mut score = 0;
472 score += match self.session_id().sender_comp_id() {
473 "*" => 6,
474 value if value == session_id.sender_comp_id() => 7,
475 _ => 0,
476 };
477 score += match self.session_id().sender_sub_id() {
478 value if value == session_id.sender_sub_id() => 1,
479 _ => 0,
480 };
481 score += match self.session_id().sender_location_id() {
482 value if value == session_id.sender_location_id() => 1,
483 _ => 0,
484 };
485 score += match self.session_id().target_comp_id() {
486 "*" => 6,
487 value if value == session_id.target_comp_id() => 7,
488 _ => 0,
489 };
490 score += match self.session_id().target_sub_id() {
491 value if value == session_id.target_sub_id() => 1,
492 _ => 0,
493 };
494 score += match self.session_id().target_location_id() {
495 value if value == session_id.target_location_id() => 1,
496 _ => 0,
497 };
498 if score < 12 {
499 0
500 } else {
501 score
502 }
503 }
504
505 pub(crate) fn is_dynamic(&self) -> bool {
506 match self.connection {
507 SettingsConnection::Acceptor { is_dynamic, .. } => {
508 is_dynamic
509 && (self.session_id.sender_comp_id() == "*"
510 || self.session_id.target_comp_id() == "*")
511 }
512 SettingsConnection::Initiator { .. } => false,
513 }
514 }
515
516 pub(crate) fn socket_settings(&self) -> SocketSettings {
517 SocketSettings::new(self.connection.socket_addr().clone(), self.socket_options.clone(), self.ssl_options.clone())
518 }
519
520 pub(crate) fn reconnect_interval(&self) -> Option<u32> {
521 match self.connection {
522 SettingsConnection::Acceptor { .. } => None,
523 SettingsConnection::Initiator { reconnect_interval, .. } => Some(reconnect_interval),
524 }
525 }
526
527 pub(crate) fn accepts(&self, session_id: &SessionId) -> bool {
528 if self.is_dynamic() {
529 let sender_comp_ok = match self.session_id.sender_comp_id() {
530 "*" => true,
531 s => s == session_id.sender_comp_id(),
532 };
533 let target_comp_ok = match self.session_id.target_comp_id() {
534 "*" => true,
535 s => s == session_id.target_comp_id(),
536 };
537 sender_comp_ok && target_comp_ok
538 } else {
539 self.session_id() == session_id
540 }
541 }
542}