1use bytes::BytesMut;
8use std::borrow::Cow;
9use std::time::Duration;
10use std::{io::Write, net::TcpStream};
11
12use crate::association::private::SyncAssociationSealed;
13use crate::association::{
14 encode_pdu, read_pdu_from_wire, AbortedSnafu, Association, CloseSocket,
15 MissingAbstractSyntaxSnafu, RejectedSnafu, SendPduSnafu, SocketOptions, SyncAssociation,
16 UnexpectedPduSnafu, UnknownPduSnafu, WireSendSnafu,
17};
18use dicom_encoding::transfer_syntax::TransferSyntaxIndex;
19use dicom_transfer_syntax_registry::TransferSyntaxRegistry;
20use snafu::{ensure, ResultExt};
21
22use crate::association::NegotiatedOptions;
23use crate::pdu::{PresentationContextNegotiated, LARGE_PDU_SIZE};
24use crate::{
25 pdu::{
26 write_pdu, AbortRQServiceProviderReason, AbortRQSource, AssociationAC, AssociationRJ,
27 AssociationRJResult, AssociationRJServiceUserReason, AssociationRJSource, AssociationRQ,
28 Pdu, PresentationContextResult, PresentationContextResultReason, UserIdentity,
29 UserVariableItem, DEFAULT_MAX_PDU, PDU_HEADER_SIZE,
30 },
31 IMPLEMENTATION_CLASS_UID, IMPLEMENTATION_VERSION_NAME,
32};
33
34use super::{uid::trim_uid, Error, Result};
35
36#[cfg(feature = "async")]
37use crate::association::AsyncAssociation;
38
39#[deprecated(since = "0.9.1")]
41pub mod non_blocking {}
42
43#[cfg(feature = "sync-tls")]
44pub type TlsStream = rustls::StreamOwned<rustls::ServerConnection, std::net::TcpStream>;
45#[cfg(feature = "async-tls")]
46pub type AsyncTlsStream = tokio_rustls::server::TlsStream<tokio::net::TcpStream>;
47
48pub trait AccessControl {
53 fn check_access(
59 &self,
60 this_ae_title: &str,
61 calling_ae_title: &str,
62 called_ae_title: &str,
63 user_identity: Option<&UserIdentity>,
64 ) -> Result<(), AssociationRJServiceUserReason>;
65}
66
67#[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)]
69pub struct AcceptAny;
70
71impl AccessControl for AcceptAny {
72 fn check_access(
73 &self,
74 _this_ae_title: &str,
75 _calling_ae_title: &str,
76 _called_ae_title: &str,
77 _user_identity: Option<&UserIdentity>,
78 ) -> Result<(), AssociationRJServiceUserReason> {
79 Ok(())
80 }
81}
82
83#[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)]
86pub struct AcceptCalledAeTitle;
87
88impl AccessControl for AcceptCalledAeTitle {
89 fn check_access(
90 &self,
91 this_ae_title: &str,
92 _calling_ae_title: &str,
93 called_ae_title: &str,
94 _user_identity: Option<&UserIdentity>,
95 ) -> Result<(), AssociationRJServiceUserReason> {
96 if this_ae_title == called_ae_title {
97 Ok(())
98 } else {
99 Err(AssociationRJServiceUserReason::CalledAETitleNotRecognized)
100 }
101 }
102}
103
104#[derive(Debug, Clone)]
284pub struct ServerAssociationOptions<'a, A> {
285 ae_access_control: A,
287 ae_title: Cow<'a, str>,
289 application_context_name: Cow<'a, str>,
291 abstract_syntax_uids: Vec<Cow<'a, str>>,
293 transfer_syntax_uids: Vec<Cow<'a, str>>,
295 protocol_version: u16,
297 max_pdu_length: u32,
299 strict: bool,
301 promiscuous: bool,
303 socket_options: SocketOptions,
305 #[cfg(feature = "sync-tls")]
307 tls_config: Option<std::sync::Arc<rustls::ServerConfig>>,
308}
309
310impl Default for ServerAssociationOptions<'_, AcceptAny> {
311 fn default() -> Self {
312 ServerAssociationOptions {
313 ae_access_control: AcceptAny,
314 ae_title: "THIS-SCP".into(),
315 application_context_name: "1.2.840.10008.3.1.1.1".into(),
316 abstract_syntax_uids: Vec::new(),
317 transfer_syntax_uids: Vec::new(),
318 protocol_version: 1,
319 max_pdu_length: DEFAULT_MAX_PDU,
320 strict: true,
321 promiscuous: false,
322 socket_options: SocketOptions::default(),
323 #[cfg(feature = "sync-tls")]
324 tls_config: None,
325 }
326 }
327}
328
329impl ServerAssociationOptions<'_, AcceptAny> {
330 pub fn new() -> Self {
332 Self::default()
333 }
334}
335
336impl<'a, A> ServerAssociationOptions<'a, A>
337where
338 A: AccessControl,
339{
340 pub fn accept_any(self) -> ServerAssociationOptions<'a, AcceptAny> {
345 self.ae_access_control(AcceptAny)
346 }
347
348 pub fn accept_called_ae_title(self) -> ServerAssociationOptions<'a, AcceptCalledAeTitle> {
354 self.ae_access_control(AcceptCalledAeTitle)
355 }
356
357 pub fn ae_access_control<P>(self, access_control: P) -> ServerAssociationOptions<'a, P>
362 where
363 P: AccessControl,
364 {
365 let ServerAssociationOptions {
366 ae_title,
367 application_context_name,
368 abstract_syntax_uids,
369 transfer_syntax_uids,
370 protocol_version,
371 max_pdu_length,
372 strict,
373 promiscuous,
374 ae_access_control: _,
375 socket_options,
376 #[cfg(feature = "sync-tls")]
377 tls_config,
378 } = self;
379
380 ServerAssociationOptions {
381 ae_access_control: access_control,
382 ae_title,
383 application_context_name,
384 abstract_syntax_uids,
385 transfer_syntax_uids,
386 protocol_version,
387 max_pdu_length,
388 strict,
389 promiscuous,
390 socket_options,
391 #[cfg(feature = "sync-tls")]
392 tls_config,
393 }
394 }
395
396 pub fn ae_title<T>(mut self, ae_title: T) -> Self
400 where
401 T: Into<Cow<'a, str>>,
402 {
403 self.ae_title = ae_title.into();
404 self
405 }
406
407 pub fn with_abstract_syntax<T>(mut self, abstract_syntax_uid: T) -> Self
410 where
411 T: Into<Cow<'a, str>>,
412 {
413 self.abstract_syntax_uids
414 .push(trim_uid(abstract_syntax_uid.into()));
415 self
416 }
417
418 pub fn with_transfer_syntax<T>(mut self, transfer_syntax_uid: T) -> Self
420 where
421 T: Into<Cow<'a, str>>,
422 {
423 self.transfer_syntax_uids
424 .push(trim_uid(transfer_syntax_uid.into()));
425 self
426 }
427
428 pub fn max_pdu_length(mut self, value: u32) -> Self {
430 self.max_pdu_length = value;
431 self
432 }
433
434 pub fn strict(mut self, strict: bool) -> Self {
438 self.strict = strict;
439 self
440 }
441
442 pub fn promiscuous(mut self, promiscuous: bool) -> Self {
445 self.promiscuous = promiscuous;
446 self
447 }
448
449 pub fn read_timeout(self, timeout: Duration) -> Self {
453 Self {
454 socket_options: SocketOptions {
455 read_timeout: Some(timeout),
456 write_timeout: self.socket_options.write_timeout,
457 connection_timeout: self.socket_options.connection_timeout,
458 },
459 ..self
460 }
461 }
462
463 pub fn write_timeout(self, timeout: Duration) -> Self {
465 Self {
466 socket_options: SocketOptions {
467 read_timeout: self.socket_options.read_timeout,
468 write_timeout: Some(timeout),
469 connection_timeout: self.socket_options.connection_timeout,
470 },
471 ..self
472 }
473 }
474
475 #[cfg(feature = "sync-tls")]
477 pub fn tls_config(mut self, config: impl Into<std::sync::Arc<rustls::ServerConfig>>) -> Self {
478 self.tls_config = Some(config.into());
479 self
480 }
481
482 #[allow(clippy::result_large_err)]
493 fn process_a_association_rq(
494 &self,
495 msg: Pdu,
496 ) -> std::result::Result<(Pdu, NegotiatedOptions), (Pdu, Error)> {
497 match msg {
498 Pdu::AssociationRQ(AssociationRQ {
499 protocol_version,
500 calling_ae_title,
501 called_ae_title,
502 application_context_name,
503 presentation_contexts,
504 user_variables,
505 }) => {
506 if protocol_version != self.protocol_version {
507 let association_rj = AssociationRJ {
508 result: AssociationRJResult::Permanent,
509 source: AssociationRJSource::ServiceUser(
510 AssociationRJServiceUserReason::NoReasonGiven,
511 ),
512 };
513 let pdu = Pdu::AssociationRJ(association_rj.clone());
514 return Err((pdu, RejectedSnafu { association_rj }.build()));
515 }
516
517 if application_context_name != self.application_context_name {
518 let association_rj = AssociationRJ {
519 result: AssociationRJResult::Permanent,
520 source: AssociationRJSource::ServiceUser(
521 AssociationRJServiceUserReason::ApplicationContextNameNotSupported,
522 ),
523 };
524 let pdu = Pdu::AssociationRJ(association_rj.clone());
525 return Err((pdu, RejectedSnafu { association_rj }.build()));
526 }
527
528 self.ae_access_control
529 .check_access(
530 &self.ae_title,
531 &calling_ae_title,
532 &called_ae_title,
533 user_variables
534 .iter()
535 .find_map(|user_variable| match user_variable {
536 UserVariableItem::UserIdentityItem(user_identity) => {
537 Some(user_identity)
538 }
539 _ => None,
540 }),
541 )
542 .map(Ok)
543 .unwrap_or_else(|reason| {
544 let association_rj = AssociationRJ {
545 result: AssociationRJResult::Permanent,
546 source: AssociationRJSource::ServiceUser(reason),
547 };
548 let pdu = Pdu::AssociationRJ(association_rj.clone());
549 Err((pdu, RejectedSnafu { association_rj }.build()))
550 })?;
551
552 let requestor_max_pdu_length = user_variables
554 .iter()
555 .find_map(|item| match item {
556 UserVariableItem::MaxLength(len) => Some(*len),
557 _ => None,
558 })
559 .unwrap_or(DEFAULT_MAX_PDU);
560
561 let requestor_max_pdu_length = if requestor_max_pdu_length == 0 {
564 u32::MAX
565 } else {
566 requestor_max_pdu_length
567 };
568
569 let presentation_contexts_negotiated: Vec<_> = presentation_contexts
570 .into_iter()
571 .map(|pc| {
572 let abstract_syntax = trim_uid(Cow::from(pc.abstract_syntax));
573 if !self.abstract_syntax_uids.contains(&abstract_syntax)
574 && !self.promiscuous
575 {
576 return PresentationContextNegotiated {
577 id: pc.id,
578 reason: PresentationContextResultReason::AbstractSyntaxNotSupported,
579 transfer_syntax: "1.2.840.10008.1.2".to_string(),
580 abstract_syntax: abstract_syntax.to_string(),
581 };
582 }
583
584 let (transfer_syntax, reason) = self
585 .choose_ts(pc.transfer_syntaxes)
586 .map(|ts| (ts, PresentationContextResultReason::Acceptance))
587 .unwrap_or_else(|| {
588 (
589 "1.2.840.10008.1.2".to_string(),
590 PresentationContextResultReason::TransferSyntaxesNotSupported,
591 )
592 });
593
594 PresentationContextNegotiated {
595 id: pc.id,
596 reason,
597 transfer_syntax,
598 abstract_syntax: abstract_syntax.to_string(),
599 }
600 })
601 .collect();
602
603 let pdu = Pdu::AssociationAC(AssociationAC {
604 protocol_version: self.protocol_version,
605 application_context_name,
606 presentation_contexts: presentation_contexts_negotiated
607 .iter()
608 .map(|pc| PresentationContextResult {
609 id: pc.id,
610 reason: pc.reason.clone(),
611 transfer_syntax: pc.transfer_syntax.clone(),
612 })
613 .collect(),
614 calling_ae_title: calling_ae_title.clone(),
615 called_ae_title,
616 user_variables: vec![
617 UserVariableItem::MaxLength(self.max_pdu_length),
618 UserVariableItem::ImplementationClassUID(
619 IMPLEMENTATION_CLASS_UID.to_string(),
620 ),
621 UserVariableItem::ImplementationVersionName(
622 IMPLEMENTATION_VERSION_NAME.to_string(),
623 ),
624 ],
625 });
626 Ok((
627 pdu,
628 NegotiatedOptions {
629 peer_max_pdu_length: requestor_max_pdu_length,
630 user_variables,
631 presentation_contexts: presentation_contexts_negotiated,
632 peer_ae_title: calling_ae_title,
633 },
634 ))
635 }
636 Pdu::ReleaseRQ => Err((Pdu::ReleaseRP, AbortedSnafu.build())),
637 pdu @ Pdu::AssociationAC { .. }
638 | pdu @ Pdu::AssociationRJ { .. }
639 | pdu @ Pdu::PData { .. }
640 | pdu @ Pdu::ReleaseRP
641 | pdu @ Pdu::AbortRQ { .. } => Err((
642 Pdu::AbortRQ {
643 source: AbortRQSource::ServiceProvider(
644 AbortRQServiceProviderReason::UnexpectedPdu,
645 ),
646 },
647 UnexpectedPduSnafu { pdu }.build(),
648 )),
649 pdu @ Pdu::Unknown { .. } => Err((
650 Pdu::AbortRQ {
651 source: AbortRQSource::ServiceProvider(
652 AbortRQServiceProviderReason::UnrecognizedPdu,
653 ),
654 },
655 UnknownPduSnafu { pdu }.build(),
656 )),
657 }
658 }
659
660 pub fn establish(&self, mut socket: TcpStream) -> Result<ServerAssociation<TcpStream>> {
662 ensure!(
663 !self.abstract_syntax_uids.is_empty() || self.promiscuous,
664 MissingAbstractSyntaxSnafu
665 );
666
667 socket
668 .set_read_timeout(self.socket_options.read_timeout)
669 .context(super::SetReadTimeoutSnafu)?;
670 socket
671 .set_write_timeout(self.socket_options.write_timeout)
672 .context(super::SetWriteTimeoutSnafu)?;
673
674 let mut read_buffer = BytesMut::with_capacity(
675 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
676 );
677 let msg = read_pdu_from_wire(
678 &mut socket,
679 &mut read_buffer,
680 self.max_pdu_length,
681 self.strict,
682 )?;
683 let mut write_buffer: Vec<u8> = Vec::with_capacity(self.max_pdu_length as usize);
684 match self.process_a_association_rq(msg) {
685 Ok((
686 pdu,
687 NegotiatedOptions {
688 user_variables,
689 presentation_contexts,
690 peer_max_pdu_length,
691 peer_ae_title,
692 },
693 )) => {
694 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
695 socket.write_all(&write_buffer).context(WireSendSnafu)?;
696 Ok(ServerAssociation {
697 presentation_contexts,
698 requestor_max_pdu_length: peer_max_pdu_length,
699 acceptor_max_pdu_length: self.max_pdu_length,
700 socket,
701 client_ae_title: peer_ae_title,
702 write_buffer,
703 strict: self.strict,
704 read_buffer,
705 user_variables,
706 })
707 }
708 Err((pdu, err)) => {
709 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
711 socket.write_all(&write_buffer).context(WireSendSnafu)?;
712 Err(err)
713 }
714 }
715 }
716
717 #[cfg(feature = "sync-tls")]
719 pub fn establish_tls(&self, socket: TcpStream) -> Result<ServerAssociation<TlsStream>> {
720 ensure!(
721 !self.abstract_syntax_uids.is_empty() || self.promiscuous,
722 MissingAbstractSyntaxSnafu
723 );
724 let tls_config = self
725 .tls_config
726 .as_ref()
727 .ok_or_else(|| super::TlsConfigMissingSnafu {}.build())?;
728
729 socket
730 .set_read_timeout(self.socket_options.read_timeout)
731 .context(super::SetReadTimeoutSnafu)?;
732 socket
733 .set_write_timeout(self.socket_options.write_timeout)
734 .context(super::SetWriteTimeoutSnafu)?;
735
736 let conn =
737 rustls::ServerConnection::new(tls_config.clone()).context(super::TlsConnectionSnafu)?;
738 let mut tls_stream = rustls::StreamOwned::new(conn, socket);
739 let mut read_buffer = BytesMut::with_capacity(
740 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
741 );
742
743 let msg = read_pdu_from_wire(
744 &mut tls_stream,
745 &mut read_buffer,
746 self.max_pdu_length,
747 self.strict,
748 )?;
749 let mut write_buffer: Vec<u8> = Vec::with_capacity(self.max_pdu_length as usize);
750 match self.process_a_association_rq(msg) {
751 Ok((
752 pdu,
753 NegotiatedOptions {
754 user_variables,
755 presentation_contexts,
756 peer_max_pdu_length,
757 peer_ae_title,
758 },
759 )) => {
760 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
761 tls_stream.write_all(&write_buffer).context(WireSendSnafu)?;
762 Ok(ServerAssociation {
763 presentation_contexts,
764 requestor_max_pdu_length: peer_max_pdu_length,
765 acceptor_max_pdu_length: self.max_pdu_length,
766 socket: tls_stream,
767 client_ae_title: peer_ae_title,
768 write_buffer,
769 strict: self.strict,
770 read_buffer,
771 user_variables,
772 })
773 }
774 Err((pdu, err)) => {
775 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
777 tls_stream.write_all(&write_buffer).context(WireSendSnafu)?;
778 Err(err)
779 }
780 }
781 }
782
783 fn choose_ts<I, T>(&self, it: I) -> Option<T>
791 where
792 I: IntoIterator<Item = T>,
793 T: AsRef<str>,
794 {
795 if self.transfer_syntax_uids.is_empty() {
796 return choose_supported(it);
797 }
798
799 it.into_iter().find(|ts| {
800 let ts = ts.as_ref();
801 if self.transfer_syntax_uids.is_empty() {
802 ts.trim_end_matches(|c: char| c.is_whitespace() || c == '\0') == "1.2.840.10008.1.2"
803 } else {
804 self.transfer_syntax_uids.contains(&trim_uid(ts.into())) && is_supported(ts)
805 }
806 })
807 }
808}
809
810#[derive(Debug)]
822pub struct ServerAssociation<S> {
823 presentation_contexts: Vec<PresentationContextNegotiated>,
825 requestor_max_pdu_length: u32,
827 acceptor_max_pdu_length: u32,
829 socket: S,
831 client_ae_title: String,
833 write_buffer: Vec<u8>,
836 strict: bool,
838 read_buffer: bytes::BytesMut,
840 user_variables: Vec<UserVariableItem>,
842}
843
844impl<S> ServerAssociation<S> {
846 pub fn presentation_contexts(&self) -> &[PresentationContextNegotiated] {
848 &self.presentation_contexts
849 }
850
851 pub fn acceptor_max_pdu_length(&self) -> u32 {
854 self.acceptor_max_pdu_length
855 }
856
857 pub fn requestor_max_pdu_length(&self) -> u32 {
860 self.requestor_max_pdu_length
861 }
862
863 #[deprecated(
865 since = "0.9.1",
866 note = "Call `peer_ae_title` from trait `Association`"
867 )]
868 pub fn client_ae_title(&self) -> &str {
869 &self.client_ae_title
870 }
871}
872
873impl<S> ServerAssociation<S>
874where
875 S: std::io::Read + std::io::Write + CloseSocket,
876{
877 pub fn send(&mut self, msg: &Pdu) -> Result<()> {
879 SyncAssociation::send(self, msg)
880 }
881
882 pub fn receive(&mut self) -> Result<Pdu> {
884 SyncAssociation::receive(self)
885 }
886
887 pub fn abort(self) -> Result<()> {
891 SyncAssociation::abort(self)
892 }
893
894 pub fn send_pdata(
900 &mut self,
901 presentation_context_id: u8,
902 ) -> crate::association::pdata::PDataWriter<&mut S> {
903 SyncAssociation::send_pdata(self, presentation_context_id)
904 }
905
906 pub fn receive_pdata(&mut self) -> crate::association::pdata::PDataReader<'_, &mut S> {
912 SyncAssociation::receive_pdata(self)
913 }
914
915 pub fn inner_stream(&mut self) -> &mut S {
925 SyncAssociation::inner_stream(self)
926 }
927}
928
929impl<S> Association for ServerAssociation<S>
930where
931 S: std::io::Read + std::io::Write + CloseSocket,
932{
933 fn presentation_contexts(&self) -> &[PresentationContextNegotiated] {
935 &self.presentation_contexts
936 }
937
938 fn acceptor_max_pdu_length(&self) -> u32 {
941 self.acceptor_max_pdu_length
942 }
943
944 fn requestor_max_pdu_length(&self) -> u32 {
947 self.requestor_max_pdu_length
948 }
949
950 fn local_max_pdu_length(&self) -> u32 {
953 self.acceptor_max_pdu_length
954 }
955
956 fn peer_max_pdu_length(&self) -> u32 {
959 self.requestor_max_pdu_length
960 }
961
962 fn peer_ae_title(&self) -> &str {
964 &self.client_ae_title
965 }
966
967 fn user_variables(&self) -> &[UserVariableItem] {
972 &self.user_variables
973 }
974}
975
976impl<S> SyncAssociationSealed<S> for ServerAssociation<S>
977where
978 S: std::io::Read + std::io::Write + CloseSocket,
979{
980 fn send(&mut self, pdu: &Pdu) -> Result<()> {
981 self.write_buffer.clear();
982 encode_pdu(
983 &mut self.write_buffer,
984 pdu,
985 self.requestor_max_pdu_length + PDU_HEADER_SIZE,
986 )?;
987 self.socket
988 .write_all(&self.write_buffer)
989 .context(WireSendSnafu)
990 }
991
992 fn receive(&mut self) -> Result<Pdu> {
993 read_pdu_from_wire(
994 &mut self.socket,
995 &mut self.read_buffer,
996 self.acceptor_max_pdu_length,
997 self.strict,
998 )
999 }
1000
1001 fn close(&mut self) -> std::io::Result<()> {
1002 self.socket.close()
1003 }
1004}
1005
1006impl<S> SyncAssociation<S> for ServerAssociation<S>
1007where
1008 S: std::io::Read + std::io::Write + CloseSocket,
1009{
1010 fn inner_stream(&mut self) -> &mut S {
1011 &mut self.socket
1012 }
1013
1014 fn get_mut(&mut self) -> (&mut S, &mut BytesMut) {
1015 let Self {
1016 socket,
1017 read_buffer,
1018 ..
1019 } = self;
1020 (socket, read_buffer)
1021 }
1022}
1023
1024pub fn is_supported_with_repo<R>(ts_repo: R, ts_uid: &str) -> bool
1035where
1036 R: TransferSyntaxIndex,
1037{
1038 ts_repo
1039 .get(ts_uid)
1040 .filter(|ts| !ts.is_unsupported())
1041 .is_some()
1042}
1043
1044pub fn is_supported(ts_uid: &str) -> bool {
1054 is_supported_with_repo(TransferSyntaxRegistry, ts_uid)
1055}
1056
1057pub fn choose_supported_with_repo<R, I, T>(ts_repo: R, it: I) -> Option<T>
1061where
1062 R: TransferSyntaxIndex,
1063 I: IntoIterator<Item = T>,
1064 T: AsRef<str>,
1065{
1066 it.into_iter()
1067 .find(|ts| is_supported_with_repo(&ts_repo, ts.as_ref()))
1068}
1069
1070pub fn choose_supported<I, T>(it: I) -> Option<T>
1074where
1075 I: IntoIterator<Item = T>,
1076 T: AsRef<str>,
1077{
1078 it.into_iter().find(|ts| is_supported(ts.as_ref()))
1079}
1080
1081#[cfg(feature = "async")]
1082impl<A> ServerAssociationOptions<'_, A>
1083where
1084 A: AccessControl,
1085{
1086 pub async fn establish_async(
1088 &self,
1089 mut socket: tokio::net::TcpStream,
1090 ) -> Result<AsyncServerAssociation<tokio::net::TcpStream>> {
1091 use tokio::io::AsyncWriteExt;
1092 ensure!(
1093 !self.abstract_syntax_uids.is_empty() || self.promiscuous,
1094 MissingAbstractSyntaxSnafu
1095 );
1096 let read_timeout = self.socket_options.read_timeout;
1097 let task = async {
1098 let mut read_buffer = BytesMut::with_capacity(
1099 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1100 );
1101 let pdu = super::read_pdu_from_wire_async(
1102 &mut socket,
1103 &mut read_buffer,
1104 self.max_pdu_length,
1105 self.strict,
1106 )
1107 .await?;
1108
1109 let mut write_buffer: Vec<u8> =
1110 Vec::with_capacity((DEFAULT_MAX_PDU + PDU_HEADER_SIZE) as usize);
1111 match self.process_a_association_rq(pdu) {
1112 Ok((
1113 pdu,
1114 NegotiatedOptions {
1115 user_variables,
1116 presentation_contexts,
1117 peer_max_pdu_length,
1118 peer_ae_title,
1119 },
1120 )) => {
1121 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
1122 socket
1123 .write_all(&write_buffer)
1124 .await
1125 .context(WireSendSnafu)?;
1126 Ok(AsyncServerAssociation {
1127 presentation_contexts,
1128 requestor_max_pdu_length: peer_max_pdu_length,
1129 acceptor_max_pdu_length: self.max_pdu_length,
1130 socket,
1131 client_ae_title: peer_ae_title,
1132 write_buffer,
1133 strict: self.strict,
1134 read_buffer,
1135 read_timeout: self.socket_options.read_timeout,
1136 write_timeout: self.socket_options.write_timeout,
1137 user_variables,
1138 })
1139 }
1140 Err((pdu, err)) => {
1141 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
1143 socket
1144 .write_all(&write_buffer)
1145 .await
1146 .context(WireSendSnafu)?;
1147 Err(err)
1148 }
1149 }
1150 };
1151 super::timeout(read_timeout, task).await
1152 }
1153
1154 #[cfg(feature = "async-tls")]
1156 pub async fn establish_tls_async(
1157 &self,
1158 socket: tokio::net::TcpStream,
1159 ) -> Result<AsyncServerAssociation<AsyncTlsStream>> {
1160 use tokio::io::AsyncWriteExt;
1161 use tokio_rustls::TlsAcceptor;
1162
1163 ensure!(
1164 !self.abstract_syntax_uids.is_empty() || self.promiscuous,
1165 MissingAbstractSyntaxSnafu
1166 );
1167 let tls_config = self
1168 .tls_config
1169 .as_ref()
1170 .ok_or_else(|| crate::association::TlsConfigMissingSnafu {}.build())?;
1171 let acceptor = TlsAcceptor::from(tls_config.clone());
1172 let mut socket = acceptor
1173 .accept(socket)
1174 .await
1175 .context(crate::association::ConnectSnafu)?;
1176 let read_timeout = self.socket_options.read_timeout;
1177 let task = async {
1178 let mut read_buffer = BytesMut::with_capacity(
1179 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1180 );
1181 let pdu = super::read_pdu_from_wire_async(
1182 &mut socket,
1183 &mut read_buffer,
1184 self.max_pdu_length,
1185 self.strict,
1186 )
1187 .await?;
1188
1189 let mut write_buffer: Vec<u8> =
1190 Vec::with_capacity((DEFAULT_MAX_PDU + PDU_HEADER_SIZE) as usize);
1191 match self.process_a_association_rq(pdu) {
1192 Ok((
1193 pdu,
1194 NegotiatedOptions {
1195 user_variables,
1196 presentation_contexts,
1197 peer_max_pdu_length,
1198 peer_ae_title,
1199 },
1200 )) => {
1201 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
1202 socket
1203 .write_all(&write_buffer)
1204 .await
1205 .context(WireSendSnafu)?;
1206 Ok(AsyncServerAssociation {
1207 presentation_contexts,
1208 requestor_max_pdu_length: peer_max_pdu_length,
1209 acceptor_max_pdu_length: self.max_pdu_length,
1210 socket,
1211 client_ae_title: peer_ae_title,
1212 write_buffer,
1213 strict: self.strict,
1214 read_buffer,
1215 read_timeout: self.socket_options.read_timeout,
1216 write_timeout: self.socket_options.write_timeout,
1217 user_variables,
1218 })
1219 }
1220 Err((pdu, err)) => {
1221 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
1223 socket
1224 .write_all(&write_buffer)
1225 .await
1226 .context(WireSendSnafu)?;
1227 Err(err)
1228 }
1229 }
1230 };
1231 super::timeout(read_timeout, task).await
1232 }
1233}
1234
1235#[cfg(feature = "async")]
1247#[derive(Debug)]
1248pub struct AsyncServerAssociation<S> {
1249 presentation_contexts: Vec<PresentationContextNegotiated>,
1251 requestor_max_pdu_length: u32,
1253 acceptor_max_pdu_length: u32,
1255 socket: S,
1257 client_ae_title: String,
1259 write_buffer: Vec<u8>,
1261 strict: bool,
1263 read_buffer: bytes::BytesMut,
1265 read_timeout: Option<std::time::Duration>,
1267 write_timeout: Option<std::time::Duration>,
1269 user_variables: Vec<UserVariableItem>,
1271}
1272
1273#[cfg(feature = "async")]
1274impl<S> Association for AsyncServerAssociation<S>
1275where
1276 S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send,
1277{
1278 fn acceptor_max_pdu_length(&self) -> u32 {
1281 self.acceptor_max_pdu_length
1282 }
1283
1284 fn requestor_max_pdu_length(&self) -> u32 {
1287 self.requestor_max_pdu_length
1288 }
1289
1290 fn local_max_pdu_length(&self) -> u32 {
1293 self.acceptor_max_pdu_length
1294 }
1295
1296 fn peer_max_pdu_length(&self) -> u32 {
1299 self.requestor_max_pdu_length
1300 }
1301
1302 fn presentation_contexts(&self) -> &[PresentationContextNegotiated] {
1304 &self.presentation_contexts
1305 }
1306
1307 fn peer_ae_title(&self) -> &str {
1309 &self.client_ae_title
1310 }
1311
1312 fn user_variables(&self) -> &[UserVariableItem] {
1313 &self.user_variables
1314 }
1315}
1316
1317#[cfg(feature = "async")]
1318impl<S> crate::association::private::AsyncAssociationSealed<S> for AsyncServerAssociation<S>
1319where
1320 S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send,
1321{
1322 async fn send(&mut self, msg: &Pdu) -> Result<()> {
1324 use tokio::io::AsyncWriteExt;
1325 self.write_buffer.clear();
1326 super::timeout(self.write_timeout, async {
1327 encode_pdu(
1328 &mut self.write_buffer,
1329 msg,
1330 self.requestor_max_pdu_length + PDU_HEADER_SIZE,
1331 )?;
1332 self.socket
1333 .write_all(&self.write_buffer)
1334 .await
1335 .context(WireSendSnafu)
1336 })
1337 .await
1338 }
1339
1340 async fn receive(&mut self) -> Result<Pdu> {
1342 super::timeout(self.read_timeout, async {
1343 super::read_pdu_from_wire_async(
1344 &mut self.socket,
1345 &mut self.read_buffer,
1346 self.acceptor_max_pdu_length,
1347 self.strict,
1348 )
1349 .await
1350 })
1351 .await
1352 }
1353
1354 async fn close(&mut self) -> std::io::Result<()> {
1355 use tokio::io::AsyncWriteExt;
1356 self.socket.shutdown().await
1357 }
1358}
1359
1360#[cfg(feature = "async")]
1361impl<S> crate::association::AsyncAssociation<S> for AsyncServerAssociation<S>
1362where
1363 S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send,
1364{
1365 fn inner_stream(&mut self) -> &mut S {
1366 &mut self.socket
1367 }
1368
1369 fn get_mut(&mut self) -> (&mut S, &mut bytes::BytesMut) {
1370 let Self {
1371 socket,
1372 read_buffer,
1373 ..
1374 } = self;
1375 (socket, read_buffer)
1376 }
1377}
1378
1379#[cfg(feature = "async")]
1381impl<S> AsyncServerAssociation<S> {
1382 pub fn presentation_contexts(&self) -> &[PresentationContextNegotiated] {
1384 &self.presentation_contexts
1385 }
1386
1387 pub fn acceptor_max_pdu_length(&self) -> u32 {
1390 self.acceptor_max_pdu_length
1391 }
1392
1393 pub fn requestor_max_pdu_length(&self) -> u32 {
1396 self.requestor_max_pdu_length
1397 }
1398
1399 #[deprecated(
1401 since = "0.9.1",
1402 note = "Call `peer_ae_title` from trait `Association`"
1403 )]
1404 pub fn client_ae_title(&self) -> &str {
1405 &self.client_ae_title
1406 }
1407}
1408
1409#[cfg(feature = "async")]
1411impl<S> AsyncServerAssociation<S>
1412where
1413 S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send,
1414{
1415 pub async fn send(&mut self, msg: &Pdu) -> Result<()> {
1417 AsyncAssociation::send(self, msg).await
1418 }
1419
1420 pub async fn receive(&mut self) -> Result<Pdu> {
1422 AsyncAssociation::receive(self).await
1423 }
1424
1425 pub async fn release(self) -> Result<()> {
1435 AsyncAssociation::release(self).await
1436 }
1437
1438 pub async fn abort(self) -> Result<()> {
1442 AsyncAssociation::abort(self).await
1443 }
1444
1445 pub fn send_pdata(
1451 &mut self,
1452 presentation_context_id: u8,
1453 ) -> crate::association::pdata::non_blocking::AsyncPDataWriter<&mut S> {
1454 AsyncAssociation::send_pdata(self, presentation_context_id)
1455 }
1456
1457 pub fn receive_pdata(&mut self) -> crate::association::pdata::PDataReader<'_, &mut S> {
1463 AsyncAssociation::receive_pdata(self)
1464 }
1465
1466 pub fn inner_stream(&mut self) -> &mut S {
1476 AsyncAssociation::inner_stream(self)
1477 }
1478}
1479
1480#[cfg(test)]
1481mod tests {
1482 use super::*;
1483
1484 #[test]
1485 fn test_choose_supported() {
1486 assert_eq!(choose_supported(vec!["1.1.1.1.1"]), None,);
1487
1488 assert_eq!(
1490 choose_supported(vec!["1.2.840.10008.1.2", "1.2.840.10008.1.2.1"]),
1491 Some("1.2.840.10008.1.2"),
1492 );
1493
1494 assert_eq!(
1496 choose_supported(vec![
1497 "1.2.840.10008.1.2.1".to_string(),
1498 "1.2.840.10008.1.2".to_string()
1499 ]),
1500 Some("1.2.840.10008.1.2.1".to_string()),
1501 );
1502 }
1503
1504 impl<'a, A> ServerAssociationOptions<'a, A>
1505 where
1506 A: AccessControl,
1507 {
1508 pub(crate) fn establish_with_extra_pdus(
1510 &self,
1511 mut socket: std::net::TcpStream,
1512 extra_pdus: Vec<Pdu>,
1513 ) -> Result<ServerAssociation<TcpStream>> {
1514 let mut read_buffer = BytesMut::with_capacity(
1515 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1516 );
1517 let pdu = read_pdu_from_wire(
1518 &mut socket,
1519 &mut read_buffer,
1520 self.max_pdu_length,
1521 self.strict,
1522 )?;
1523 let (
1524 pdu,
1525 NegotiatedOptions {
1526 user_variables,
1527 presentation_contexts,
1528 peer_max_pdu_length,
1529 peer_ae_title,
1530 },
1531 ) = self
1532 .process_a_association_rq(pdu)
1533 .expect("Could not parse association req");
1534
1535 let mut write_buffer: Vec<u8> =
1536 Vec::with_capacity((DEFAULT_MAX_PDU + PDU_HEADER_SIZE) as usize);
1537 write_pdu(&mut write_buffer, &pdu).context(SendPduSnafu)?;
1538 for extra_pdu in extra_pdus {
1539 write_pdu(&mut write_buffer, &extra_pdu).context(SendPduSnafu)?;
1540 }
1541 socket.write_all(&write_buffer).context(WireSendSnafu)?;
1542
1543 Ok(ServerAssociation {
1544 presentation_contexts,
1545 requestor_max_pdu_length: peer_max_pdu_length,
1546 acceptor_max_pdu_length: self.max_pdu_length,
1547 socket,
1548 client_ae_title: peer_ae_title,
1549 write_buffer,
1550 read_buffer,
1551 strict: self.strict,
1552 user_variables,
1553 })
1554 }
1555
1556 #[cfg(feature = "async")]
1558 pub(crate) async fn establish_with_extra_pdus_async(
1559 &self,
1560 mut socket: tokio::net::TcpStream,
1561 extra_pdus: Vec<Pdu>,
1562 ) -> Result<AsyncServerAssociation<tokio::net::TcpStream>> {
1563 use tokio::io::AsyncWriteExt;
1564
1565 use crate::association::read_pdu_from_wire_async;
1566
1567 let mut read_buffer = BytesMut::with_capacity(
1568 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1569 );
1570 let pdu = read_pdu_from_wire_async(
1571 &mut socket,
1572 &mut read_buffer,
1573 self.max_pdu_length,
1574 self.strict,
1575 )
1576 .await?;
1577 let (
1578 pdu,
1579 NegotiatedOptions {
1580 user_variables,
1581 presentation_contexts,
1582 peer_max_pdu_length,
1583 peer_ae_title,
1584 },
1585 ) = self
1586 .process_a_association_rq(pdu)
1587 .expect("Could not parse association req");
1588
1589 let mut buffer: Vec<u8> = Vec::with_capacity(
1590 (peer_max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1591 );
1592 write_pdu(&mut buffer, &pdu).context(SendPduSnafu)?;
1593 for extra_pdu in extra_pdus {
1594 write_pdu(&mut buffer, &extra_pdu).context(SendPduSnafu)?;
1595 }
1596 socket.write_all(&buffer).await.context(WireSendSnafu)?;
1597
1598 Ok(AsyncServerAssociation {
1599 presentation_contexts,
1600 requestor_max_pdu_length: peer_max_pdu_length,
1601 acceptor_max_pdu_length: self.max_pdu_length,
1602 socket,
1603 client_ae_title: peer_ae_title,
1604 write_buffer: buffer,
1605 strict: self.strict,
1606 read_buffer: BytesMut::with_capacity(
1607 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1608 ),
1609 user_variables,
1610 read_timeout: self.socket_options.read_timeout,
1611 write_timeout: self.socket_options.write_timeout,
1612 })
1613 }
1614
1615 pub fn broken_establish(
1617 &self,
1618 mut socket: TcpStream,
1619 ) -> Result<ServerAssociation<TcpStream>> {
1620 let mut read_buffer = BytesMut::with_capacity(
1621 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1622 );
1623 let msg = read_pdu_from_wire(
1624 &mut socket,
1625 &mut read_buffer,
1626 self.max_pdu_length,
1627 self.strict,
1628 )?;
1629 let (
1630 pdu,
1631 NegotiatedOptions {
1632 user_variables,
1633 presentation_contexts,
1634 peer_max_pdu_length,
1635 peer_ae_title,
1636 },
1637 ) = self
1638 .process_a_association_rq(msg)
1639 .expect("Could not parse association req");
1640 let mut buffer: Vec<u8> = Vec::with_capacity(
1641 (peer_max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1642 );
1643 write_pdu(&mut buffer, &pdu).context(SendPduSnafu)?;
1644 socket.write_all(&buffer).context(WireSendSnafu)?;
1645 Ok(ServerAssociation {
1646 presentation_contexts,
1647 requestor_max_pdu_length: peer_max_pdu_length,
1648 acceptor_max_pdu_length: self.max_pdu_length,
1649 socket,
1650 client_ae_title: peer_ae_title,
1651 write_buffer: buffer,
1652 strict: self.strict,
1653 read_buffer: BytesMut::with_capacity(
1654 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1655 ),
1656 user_variables,
1657 })
1658 }
1659
1660 #[cfg(feature = "async")]
1662 pub async fn broken_establish_async(
1663 &self,
1664 mut socket: tokio::net::TcpStream,
1665 ) -> Result<AsyncServerAssociation<tokio::net::TcpStream>> {
1666 use tokio::io::AsyncWriteExt;
1667
1668 use crate::association::read_pdu_from_wire_async;
1669
1670 let mut read_buffer = BytesMut::with_capacity(
1671 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1672 );
1673 let msg = read_pdu_from_wire_async(
1674 &mut socket,
1675 &mut read_buffer,
1676 self.max_pdu_length,
1677 self.strict,
1678 )
1679 .await?;
1680 let (
1681 pdu,
1682 NegotiatedOptions {
1683 user_variables,
1684 presentation_contexts,
1685 peer_max_pdu_length,
1686 peer_ae_title,
1687 },
1688 ) = self
1689 .process_a_association_rq(msg)
1690 .expect("Could not parse association req");
1691 let mut buffer: Vec<u8> = Vec::with_capacity(
1692 (peer_max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1693 );
1694 write_pdu(&mut buffer, &pdu).context(SendPduSnafu)?;
1695 socket.write_all(&buffer).await.context(WireSendSnafu)?;
1696 Ok(AsyncServerAssociation {
1697 presentation_contexts,
1698 requestor_max_pdu_length: peer_max_pdu_length,
1699 acceptor_max_pdu_length: self.max_pdu_length,
1700 socket,
1701 client_ae_title: peer_ae_title,
1702 write_buffer: buffer,
1703 strict: self.strict,
1704 read_buffer: BytesMut::with_capacity(
1705 (self.max_pdu_length.min(LARGE_PDU_SIZE) + PDU_HEADER_SIZE) as usize,
1706 ),
1707 read_timeout: self.socket_options.read_timeout,
1708 write_timeout: self.socket_options.write_timeout,
1709 user_variables,
1710 })
1711 }
1712 }
1713}