1use std::time::Duration;
5
6use slim_auth::metadata::MetadataMap;
7use slim_config::grpc::server::KeepaliveServerParameters as CoreKeepaliveServerParameters;
8use slim_config::grpc::server::ServerConfig as CoreServerConfig;
9
10use crate::common_config::{ServerAuthenticationConfig, TlsServerConfig, TlsSource};
11use crate::transport_protocol::TransportProtocol;
12
13#[derive(uniffi::Record, Clone, Debug, PartialEq)]
15pub struct KeepaliveServerParameters {
16 pub max_connection_idle: Duration,
18
19 pub max_connection_age: Duration,
21
22 pub max_connection_age_grace: Duration,
24
25 pub time: Duration,
27
28 pub timeout: Duration,
30}
31
32impl Default for KeepaliveServerParameters {
33 fn default() -> Self {
34 let core_defaults = CoreKeepaliveServerParameters::default();
35 KeepaliveServerParameters {
36 max_connection_idle: *core_defaults.max_connection_idle,
37 max_connection_age: *core_defaults.max_connection_age,
38 max_connection_age_grace: *core_defaults.max_connection_age_grace,
39 time: *core_defaults.time,
40 timeout: *core_defaults.timeout,
41 }
42 }
43}
44
45impl From<KeepaliveServerParameters> for CoreKeepaliveServerParameters {
46 fn from(config: KeepaliveServerParameters) -> Self {
47 CoreKeepaliveServerParameters {
48 max_connection_idle: config.max_connection_idle.into(),
49 max_connection_age: config.max_connection_age.into(),
50 max_connection_age_grace: config.max_connection_age_grace.into(),
51 time: config.time.into(),
52 timeout: config.timeout.into(),
53 }
54 }
55}
56
57impl From<CoreKeepaliveServerParameters> for KeepaliveServerParameters {
58 fn from(config: CoreKeepaliveServerParameters) -> Self {
59 KeepaliveServerParameters {
60 max_connection_idle: *config.max_connection_idle,
61 max_connection_age: *config.max_connection_age,
62 max_connection_age_grace: *config.max_connection_age_grace,
63 time: *config.time,
64 timeout: *config.timeout,
65 }
66 }
67}
68
69#[derive(uniffi::Record, Clone, Debug, PartialEq)]
71pub struct ServerConfig {
72 pub endpoint: String,
74
75 pub transport: Option<TransportProtocol>,
77
78 pub tls: TlsServerConfig,
80
81 pub http2_only: Option<bool>,
83
84 pub max_frame_size: Option<u32>,
86
87 pub max_concurrent_streams: Option<u32>,
89
90 pub max_header_list_size: Option<u32>,
92
93 pub read_buffer_size: Option<u64>,
95
96 pub write_buffer_size: Option<u64>,
98
99 pub keepalive: Option<KeepaliveServerParameters>,
101
102 pub auth: Option<ServerAuthenticationConfig>,
104
105 pub metadata: Option<String>,
107}
108
109impl Default for ServerConfig {
110 fn default() -> Self {
111 let core_defaults = CoreServerConfig::default();
112 ServerConfig {
113 endpoint: core_defaults.endpoint,
114 transport: None,
115 tls: core_defaults.tls_setting.into(),
116 http2_only: None,
117 max_frame_size: None,
118 max_concurrent_streams: None,
119 max_header_list_size: None,
120 read_buffer_size: None,
121 write_buffer_size: None,
122 keepalive: None,
123 auth: None,
124 metadata: None,
125 }
126 }
127}
128
129impl From<ServerConfig> for CoreServerConfig {
130 fn from(config: ServerConfig) -> Self {
131 let core_defaults = CoreServerConfig::default();
132 CoreServerConfig {
133 endpoint: config.endpoint,
134 transport: config
135 .transport
136 .map(Into::into)
137 .unwrap_or(core_defaults.transport),
138 tls_setting: config.tls.into(),
139 http2_only: config.http2_only.unwrap_or(core_defaults.http2_only),
140 max_frame_size: config.max_frame_size.or(core_defaults.max_frame_size),
141 max_concurrent_streams: config
142 .max_concurrent_streams
143 .or(core_defaults.max_concurrent_streams),
144 max_header_list_size: config
145 .max_header_list_size
146 .or(core_defaults.max_header_list_size),
147 read_buffer_size: config
148 .read_buffer_size
149 .map(|s| s as usize)
150 .or(core_defaults.read_buffer_size),
151 write_buffer_size: config
152 .write_buffer_size
153 .map(|s| s as usize)
154 .or(core_defaults.write_buffer_size),
155 keepalive: config
156 .keepalive
157 .map(Into::into)
158 .unwrap_or(core_defaults.keepalive),
159 auth: config.auth.map(Into::into).unwrap_or(core_defaults.auth),
160 metadata: config
161 .metadata
162 .and_then(|json| serde_json::from_str::<MetadataMap>(&json).ok()),
163 }
164 }
165}
166
167impl From<CoreServerConfig> for ServerConfig {
168 fn from(config: CoreServerConfig) -> Self {
169 ServerConfig {
170 endpoint: config.endpoint,
171 transport: Some(config.transport.into()),
172 tls: config.tls_setting.into(),
173 http2_only: Some(config.http2_only),
174 max_frame_size: config.max_frame_size,
175 max_concurrent_streams: config.max_concurrent_streams,
176 max_header_list_size: config.max_header_list_size,
177 read_buffer_size: config.read_buffer_size.map(|s| s as u64),
178 write_buffer_size: config.write_buffer_size.map(|s| s as u64),
179 keepalive: Some(config.keepalive.into()),
180 auth: Some(config.auth.into()),
181 metadata: config.metadata.and_then(|m| serde_json::to_string(&m).ok()),
182 }
183 }
184}
185
186#[uniffi::export]
188pub fn new_server_config(endpoint: String) -> ServerConfig {
189 ServerConfig {
190 endpoint,
191 ..Default::default()
192 }
193}
194
195#[uniffi::export]
197pub fn new_insecure_server_config(endpoint: String) -> ServerConfig {
198 ServerConfig {
199 endpoint,
200 tls: TlsServerConfig {
201 insecure: true,
202 ..Default::default()
203 },
204 ..Default::default()
205 }
206}
207
208#[uniffi::export]
210pub fn new_secure_server_config(endpoint: String, tls_source: TlsSource) -> ServerConfig {
211 ServerConfig {
212 endpoint,
213 tls: TlsServerConfig {
214 insecure: false,
215 source: tls_source,
216 ..Default::default()
217 },
218 ..Default::default()
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225 use crate::common_config::{CaSource, TlsSource};
226 use slim_config::transport::TransportProtocol as CoreTransportProtocol;
227
228 #[test]
229 fn test_server_config_creation() {
230 let config = ServerConfig {
231 endpoint: "127.0.0.1:8080".to_string(),
232 tls: TlsServerConfig {
233 insecure: false,
234 source: TlsSource::File {
235 cert: "/cert.pem".to_string(),
236 key: "/key.pem".to_string(),
237 },
238 client_ca: CaSource::None,
239 include_system_ca_certs_pool: Some(true),
240 tls_version: Some("tls1.3".to_string()),
241 reload_client_ca_file: Some(false),
242 },
243 http2_only: Some(true),
244 ..Default::default()
245 };
246
247 assert_eq!(config.endpoint, "127.0.0.1:8080");
248 assert!(!config.tls.insecure);
249 assert_eq!(config.tls.tls_version, Some("tls1.3".to_string()));
250 assert_eq!(config.http2_only, Some(true));
251 }
252
253 #[test]
254 fn test_server_config_default() {
255 let config = ServerConfig::default();
256
257 assert_eq!(config.endpoint, "");
259 assert_eq!(config.transport, None);
260 assert_eq!(config.http2_only, None);
261 assert_eq!(config.max_frame_size, None);
262 assert_eq!(config.max_concurrent_streams, None);
263 assert_eq!(config.max_header_list_size, None);
264 assert_eq!(config.read_buffer_size, None);
265 assert_eq!(config.write_buffer_size, None);
266 assert_eq!(config.keepalive, None);
267 assert_eq!(config.auth, None);
268 assert_eq!(config.metadata, None);
269
270 let core: CoreServerConfig = config.into();
272 assert!(core.http2_only);
273 assert_eq!(core.max_frame_size, Some(4));
274 assert_eq!(core.max_concurrent_streams, Some(100));
275 assert_eq!(core.read_buffer_size, Some(1024 * 1024));
276 assert_eq!(core.write_buffer_size, Some(1024 * 1024));
277 assert_eq!(
278 core.auth,
279 slim_config::grpc::server::AuthenticationConfig::None
280 );
281 }
282
283 #[test]
284 fn test_server_config_new() {
285 let config = new_server_config("0.0.0.0:50051".to_string());
286
287 assert_eq!(config.endpoint, "0.0.0.0:50051");
288 assert_eq!(config.http2_only, None);
290 assert_eq!(config.auth, None);
291 }
292
293 #[test]
294 fn test_server_config_new_insecure() {
295 let config = new_insecure_server_config("[::]:50051".to_string());
296
297 assert_eq!(config.endpoint, "[::]:50051");
298 assert!(config.tls.insecure);
299 assert_eq!(config.http2_only, None);
300 }
301
302 #[test]
303 fn test_server_config_new_secure() {
304 let config = new_secure_server_config(
305 "0.0.0.0:443".to_string(),
306 TlsSource::File {
307 cert: "/etc/tls/server.crt".to_string(),
308 key: "/etc/tls/server.key".to_string(),
309 },
310 );
311
312 assert_eq!(config.endpoint, "0.0.0.0:443");
313 assert!(!config.tls.insecure);
314 assert_eq!(
315 config.tls.source,
316 TlsSource::File {
317 cert: "/etc/tls/server.crt".to_string(),
318 key: "/etc/tls/server.key".to_string(),
319 }
320 );
321 assert_eq!(config.http2_only, None);
323 assert_eq!(config.max_frame_size, None);
324 assert_eq!(config.max_concurrent_streams, None);
325 assert_eq!(config.keepalive, None);
326 assert_eq!(config.auth, None);
327 assert_eq!(config.metadata, None);
328 }
329
330 #[test]
331 fn test_server_config_to_core_conversion() {
332 let ffi_config = ServerConfig {
333 endpoint: "127.0.0.1:8080".to_string(),
334 transport: Some(TransportProtocol::Websocket),
335 tls: TlsServerConfig::default(),
336 http2_only: Some(false),
337 max_frame_size: Some(8),
338 max_concurrent_streams: Some(200),
339 max_header_list_size: Some(8192),
340 read_buffer_size: Some(2048),
341 write_buffer_size: Some(2048),
342 keepalive: Some(KeepaliveServerParameters::default()),
343 auth: Some(ServerAuthenticationConfig::None),
344 metadata: Some(r#"{"key":"value"}"#.to_string()),
345 };
346
347 let core_config: CoreServerConfig = ffi_config.into();
348
349 assert_eq!(core_config.endpoint, "127.0.0.1:8080");
350 assert_eq!(core_config.transport, CoreTransportProtocol::Websocket);
351 assert!(!core_config.http2_only);
352 assert_eq!(core_config.max_frame_size, Some(8));
353 assert_eq!(core_config.max_concurrent_streams, Some(200));
354 assert_eq!(core_config.max_header_list_size, Some(8192));
355 assert_eq!(core_config.read_buffer_size, Some(2048));
356 assert_eq!(core_config.write_buffer_size, Some(2048));
357 assert!(core_config.metadata.is_some());
358 }
359
360 #[test]
361 fn test_server_config_from_core_conversion() {
362 let core_config = CoreServerConfig::default();
364
365 let ffi_config: ServerConfig = core_config.clone().into();
367
368 assert_eq!(ffi_config.endpoint, core_config.endpoint);
369 assert_eq!(ffi_config.transport, Some(core_config.transport.into()));
370 assert_eq!(ffi_config.http2_only, Some(core_config.http2_only));
371 assert_eq!(ffi_config.max_frame_size, core_config.max_frame_size);
372 assert_eq!(
373 ffi_config.max_concurrent_streams,
374 core_config.max_concurrent_streams
375 );
376 assert_eq!(
377 ffi_config.max_header_list_size,
378 core_config.max_header_list_size
379 );
380 }
381
382 #[test]
383 fn test_server_config_roundtrip_conversion() {
384 let original = ServerConfig {
385 endpoint: "localhost:9090".to_string(),
386 transport: Some(TransportProtocol::Grpc),
387 tls: TlsServerConfig::default(),
388 http2_only: Some(true),
389 max_frame_size: Some(16),
390 max_concurrent_streams: Some(500),
391 max_header_list_size: Some(16384),
392 read_buffer_size: Some(4096),
393 write_buffer_size: Some(4096),
394 keepalive: Some(KeepaliveServerParameters::default()),
395 auth: Some(ServerAuthenticationConfig::None),
396 metadata: None,
397 };
398
399 let core: CoreServerConfig = original.clone().into();
401 let roundtrip: ServerConfig = core.into();
402
403 assert_eq!(roundtrip.endpoint, original.endpoint);
404 assert_eq!(roundtrip.transport, original.transport);
405 assert_eq!(roundtrip.http2_only, original.http2_only);
406 assert_eq!(roundtrip.max_frame_size, original.max_frame_size);
407 assert_eq!(
408 roundtrip.max_concurrent_streams,
409 original.max_concurrent_streams
410 );
411 assert_eq!(
412 roundtrip.max_header_list_size,
413 original.max_header_list_size
414 );
415 assert_eq!(roundtrip.read_buffer_size, original.read_buffer_size);
416 assert_eq!(roundtrip.write_buffer_size, original.write_buffer_size);
417 }
418
419 #[test]
420 fn test_keepalive_defaults() {
421 let keepalive = KeepaliveServerParameters::default();
422
423 assert!(keepalive.max_connection_idle.as_secs() > 0);
425 assert!(keepalive.max_connection_age.as_secs() > 0);
426 assert!(keepalive.time.as_secs() > 0);
427 assert!(keepalive.timeout.as_secs() > 0);
428 }
429
430 #[test]
431 fn test_keepalive_conversion() {
432 let ffi_keepalive = KeepaliveServerParameters {
433 max_connection_idle: Duration::from_secs(600),
434 max_connection_age: Duration::from_secs(1800),
435 max_connection_age_grace: Duration::from_secs(60),
436 time: Duration::from_secs(300),
437 timeout: Duration::from_secs(20),
438 };
439
440 let core_keepalive: CoreKeepaliveServerParameters = ffi_keepalive.into();
441
442 assert_eq!(
443 *core_keepalive.max_connection_idle,
444 Duration::from_secs(600)
445 );
446 assert_eq!(
447 *core_keepalive.max_connection_age,
448 Duration::from_secs(1800)
449 );
450 assert_eq!(
451 *core_keepalive.max_connection_age_grace,
452 Duration::from_secs(60)
453 );
454 assert_eq!(*core_keepalive.time, Duration::from_secs(300));
455 assert_eq!(*core_keepalive.timeout, Duration::from_secs(20));
456 }
457
458 #[test]
459 fn test_metadata_serialization() {
460 let config = ServerConfig {
461 endpoint: "test:8080".to_string(),
462 tls: TlsServerConfig::default(),
463 metadata: Some(r#"{"env":"test","version":1}"#.to_string()),
464 ..Default::default()
465 };
466
467 let core: CoreServerConfig = config.into();
468
469 assert!(core.metadata.is_some());
471 let metadata = core.metadata.unwrap();
472 assert_eq!(metadata.len(), 2);
473 }
474
475 #[test]
476 fn test_metadata_invalid_json() {
477 let config = ServerConfig {
478 endpoint: "test:8080".to_string(),
479 tls: TlsServerConfig::default(),
480 metadata: Some("invalid json".to_string()),
481 ..Default::default()
482 };
483
484 let core: CoreServerConfig = config.into();
485
486 assert!(core.metadata.is_none());
488 }
489
490 #[test]
491 fn test_basic_auth_roundtrip() {
492 use crate::common_config::BasicAuth;
493
494 let basic_config = BasicAuth {
495 username: "admin".to_string(),
496 password: "secret123".to_string(),
497 };
498
499 let auth = ServerAuthenticationConfig::Basic {
500 config: basic_config.clone(),
501 };
502
503 let core_auth: slim_config::grpc::server::AuthenticationConfig = auth.into();
505 let roundtrip_auth: ServerAuthenticationConfig = core_auth.into();
506
507 if let ServerAuthenticationConfig::Basic { config } = roundtrip_auth {
509 assert_eq!(config.username, basic_config.username);
510 assert_eq!(config.password, basic_config.password);
511 } else {
512 panic!("Expected Basic authentication config");
513 }
514 }
515
516 #[test]
517 fn test_jwt_auth_roundtrip() {
518 use crate::identity_config::{
519 JwtAlgorithm, JwtAuth, JwtKeyConfig, JwtKeyData, JwtKeyFormat, JwtKeyType,
520 };
521
522 let jwt_config = JwtAuth {
523 key: JwtKeyType::Decoding {
524 key: JwtKeyConfig {
525 algorithm: JwtAlgorithm::RS256,
526 format: JwtKeyFormat::Pem,
527 key: JwtKeyData::File {
528 path: "/path/to/public_key.pem".to_string(),
529 },
530 },
531 },
532 audience: Some(vec!["api.example.com".to_string()]),
533 issuer: Some("auth.example.com".to_string()),
534 subject: Some("service123".to_string()),
535 duration: Duration::from_secs(7200),
536 };
537
538 let auth = ServerAuthenticationConfig::Jwt {
539 config: jwt_config.clone(),
540 };
541
542 let core_auth: slim_config::grpc::server::AuthenticationConfig = auth.into();
544 let roundtrip_auth: ServerAuthenticationConfig = core_auth.into();
545
546 if let ServerAuthenticationConfig::Jwt { config } = roundtrip_auth {
548 assert_eq!(config.key, jwt_config.key);
549 assert_eq!(config.audience, jwt_config.audience);
550 assert_eq!(config.issuer, jwt_config.issuer);
551 assert_eq!(config.subject, jwt_config.subject);
552 } else {
554 panic!("Expected Jwt authentication config");
555 }
556 }
557
558 #[test]
559 fn test_server_config_from_core_with_all_fields() {
560 use slim_auth::metadata::MetadataMap;
562
563 let mut metadata = MetadataMap::new();
564 metadata.insert("service".to_string(), "test-server".to_string());
565 metadata.insert("region".to_string(), "us-east-1".to_string());
566
567 let core_config = CoreServerConfig {
568 endpoint: "0.0.0.0:8443".to_string(),
569 http2_only: false,
570 max_frame_size: Some(32),
571 max_concurrent_streams: Some(1000),
572 max_header_list_size: Some(32768),
573 read_buffer_size: Some(16384),
574 write_buffer_size: Some(16384),
575 metadata: Some(metadata),
576 ..Default::default()
577 };
578
579 let ffi_config: ServerConfig = core_config.clone().into();
581
582 assert_eq!(ffi_config.endpoint, "0.0.0.0:8443");
584 assert_eq!(ffi_config.http2_only, Some(false));
585 assert_eq!(ffi_config.max_frame_size, Some(32));
586 assert_eq!(ffi_config.max_concurrent_streams, Some(1000));
587 assert_eq!(ffi_config.max_header_list_size, Some(32768));
588 assert_eq!(ffi_config.read_buffer_size, Some(16384));
589 assert_eq!(ffi_config.write_buffer_size, Some(16384));
590
591 assert!(ffi_config.metadata.is_some());
593 let metadata_str = ffi_config.metadata.unwrap();
594 assert!(metadata_str.contains("test-server"));
595 assert!(metadata_str.contains("us-east-1"));
596 }
597
598 #[test]
599 fn test_server_config_from_core_with_keepalive() {
600 use slim_config::grpc::server::KeepaliveServerParameters as CoreKeepaliveServerParameters;
601
602 let core_config = CoreServerConfig {
603 keepalive: CoreKeepaliveServerParameters {
604 max_connection_idle: Duration::from_secs(300).into(),
605 max_connection_age: Duration::from_secs(900).into(),
606 max_connection_age_grace: Duration::from_secs(30).into(),
607 time: Duration::from_secs(150).into(),
608 timeout: Duration::from_secs(15).into(),
609 },
610 ..Default::default()
611 };
612
613 let ffi_config: ServerConfig = core_config.into();
614
615 let keepalive = ffi_config.keepalive.unwrap();
616 assert_eq!(keepalive.max_connection_idle, Duration::from_secs(300));
617 assert_eq!(keepalive.max_connection_age, Duration::from_secs(900));
618 assert_eq!(keepalive.max_connection_age_grace, Duration::from_secs(30));
619 assert_eq!(keepalive.time, Duration::from_secs(150));
620 assert_eq!(keepalive.timeout, Duration::from_secs(15));
621 }
622
623 #[test]
624 fn test_server_config_from_core_buffer_size_conversion() {
625 let core_config = CoreServerConfig {
627 read_buffer_size: Some(8192),
628 write_buffer_size: Some(8192),
629 ..Default::default()
630 };
631
632 let ffi_config: ServerConfig = core_config.into();
633
634 assert_eq!(ffi_config.read_buffer_size, Some(8192u64));
635 assert_eq!(ffi_config.write_buffer_size, Some(8192u64));
636 }
637
638 #[test]
639 fn test_server_config_from_core_no_buffer_sizes() {
640 let core_config = CoreServerConfig {
642 read_buffer_size: None,
643 write_buffer_size: None,
644 ..Default::default()
645 };
646
647 let ffi_config: ServerConfig = core_config.into();
648
649 assert!(ffi_config.read_buffer_size.is_none());
650 assert!(ffi_config.write_buffer_size.is_none());
651 }
652
653 #[test]
654 fn test_server_config_from_core_http2_only_variations() {
655 let core_config_true = CoreServerConfig {
657 http2_only: true,
658 ..Default::default()
659 };
660
661 let ffi_config_true: ServerConfig = core_config_true.into();
662 assert_eq!(ffi_config_true.http2_only, Some(true));
663
664 let core_config_false = CoreServerConfig {
665 http2_only: false,
666 ..Default::default()
667 };
668
669 let ffi_config_false: ServerConfig = core_config_false.into();
670 assert_eq!(ffi_config_false.http2_only, Some(false));
671 }
672
673 #[test]
674 fn test_server_config_from_core_with_optional_fields() {
675 let core_config = CoreServerConfig {
677 max_frame_size: None,
678 max_concurrent_streams: Some(250),
679 max_header_list_size: None,
680 ..Default::default()
681 };
682
683 let ffi_config: ServerConfig = core_config.into();
684
685 assert!(ffi_config.max_frame_size.is_none());
686 assert_eq!(ffi_config.max_concurrent_streams, Some(250));
687 assert!(ffi_config.max_header_list_size.is_none());
688 }
689
690 #[test]
691 fn test_server_config_from_core_metadata_serialization_failure() {
692 let core_config = CoreServerConfig {
694 metadata: None,
695 ..Default::default()
696 };
697
698 let ffi_config: ServerConfig = core_config.into();
699
700 assert!(ffi_config.metadata.is_none());
701 }
702
703 #[test]
704 fn test_server_config_from_core_auth_types() {
705 use slim_config::auth::basic::Config as BasicAuthConfig;
706 use slim_config::grpc::server::AuthenticationConfig as CoreAuthConfig;
707
708 let core_config = CoreServerConfig {
710 auth: CoreAuthConfig::Basic(BasicAuthConfig::new("server_user", "server_pass")),
711 ..Default::default()
712 };
713
714 let ffi_config: ServerConfig = core_config.into();
715
716 match ffi_config.auth.unwrap() {
717 ServerAuthenticationConfig::Basic { config } => {
718 assert_eq!(config.username, "server_user");
719 assert_eq!(config.password, "server_pass");
720 }
721 _ => panic!("Expected Basic auth"),
722 }
723 }
724
725 #[test]
726 fn test_server_config_from_core_auth_none() {
727 use slim_config::grpc::server::AuthenticationConfig as CoreAuthConfig;
728
729 let core_config = CoreServerConfig {
731 auth: CoreAuthConfig::None,
732 ..Default::default()
733 };
734
735 let ffi_config: ServerConfig = core_config.into();
736
737 match ffi_config.auth.unwrap() {
738 ServerAuthenticationConfig::None => {
739 }
741 _ => panic!("Expected None auth"),
742 }
743 }
744
745 #[test]
746 fn test_keepalive_server_parameters_roundtrip() {
747 let original = KeepaliveServerParameters {
749 max_connection_idle: Duration::from_secs(500),
750 max_connection_age: Duration::from_secs(1500),
751 max_connection_age_grace: Duration::from_secs(50),
752 time: Duration::from_secs(250),
753 timeout: Duration::from_secs(25),
754 };
755
756 let core: CoreKeepaliveServerParameters = original.clone().into();
757 let roundtrip: KeepaliveServerParameters = core.into();
758
759 assert_eq!(roundtrip.max_connection_idle, original.max_connection_idle);
760 assert_eq!(roundtrip.max_connection_age, original.max_connection_age);
761 assert_eq!(
762 roundtrip.max_connection_age_grace,
763 original.max_connection_age_grace
764 );
765 assert_eq!(roundtrip.time, original.time);
766 assert_eq!(roundtrip.timeout, original.timeout);
767 }
768}