1pub(crate) mod api;
2pub(crate) mod messages;
3pub(crate) mod service;
4
5pub use api::*;
6use rusty_copp::{RustyCoppInitiatorIsoStack, RustyCoppReaderIsoStack, RustyCoppResponderIsoStack, RustyCoppWriterIsoStack};
7pub use service::*;
8
9pub type RustyOsiSingleValueAcseReaderIsoStack<R> = RustyOsiSingleValueAcseReader<RustyCoppReaderIsoStack<R>>;
10pub type RustyOsiSingleValueAcseWriterIsoStack<W> = RustyOsiSingleValueAcseWriter<RustyCoppWriterIsoStack<W>>;
11pub type RustyOsiSingleValueAcseInitiatorIsoStack<R, W> = RustyOsiSingleValueAcseInitiator<RustyCoppInitiatorIsoStack<R, W>, RustyCoppReaderIsoStack<R>, RustyCoppWriterIsoStack<W>>;
12pub type RustyOsiSingleValueAcseListenerIsoStack<R, W> = RustyOsiSingleValueAcseListener<RustyCoppResponderIsoStack<R, W>, RustyCoppReaderIsoStack<R>, RustyCoppWriterIsoStack<W>>;
13pub type RustyOsiSingleValueAcseResponderIsoStack<R, W> = RustyOsiSingleValueAcseResponder<RustyCoppResponderIsoStack<R, W>, RustyCoppReaderIsoStack<R>, RustyCoppWriterIsoStack<W>>;
14pub type RustyOsiSingleValueAcseConnectionIsoStack<R, W> = RustyAcseConnection<RustyCoppReaderIsoStack<R>, RustyCoppWriterIsoStack<W>>;
15
16#[cfg(test)]
17mod tests {
18 use der_parser::num_bigint::BigInt;
19 use std::time::Duration;
20
21 use der_parser::Oid;
22 use rusty_copp::{CoppError, RustyCoppListener};
23 use rusty_cosp::{TcpCospInitiator, TcpCospListener, TcpCospReader, TcpCospResponder, TcpCospWriter};
24 use rusty_cotp::{CotpAcceptInformation, CotpConnectInformation, CotpResponder, TcpCotpAcceptor, TcpCotpConnection, TcpCotpReader, TcpCotpWriter};
25 use rusty_tpkt::{TcpTpktConnection, TcpTpktReader, TcpTpktServer, TcpTpktWriter};
26 use tokio::join;
27 use tracing_test::traced_test;
28
29 use super::*;
30
31 #[tokio::test]
32 #[traced_test]
33 async fn it_should_create_connection() -> Result<(), anyhow::Error> {
34 let (client, server) = create_acse_connection_pair_with_options(
35 AcseRequestInformation {
36 application_context_name: Oid::from(&[1, 0, 9506, 2, 1])?,
37 called_ap_title: Some(ApTitle::Form2(Oid::from(&[1, 2, 3, 4, 5])?)),
38 called_ae_qualifier: Some(AeQualifier::Form2(vec![100])),
39 called_ap_invocation_identifier: Some(vec![101]),
40 called_ae_invocation_identifier: Some(vec![102]),
41 calling_ap_title: Some(ApTitle::Form2(Oid::from(&[2, 2, 3, 4, 5])?)),
42 calling_ae_qualifier: Some(AeQualifier::Form2(BigInt::from(200u32).to_signed_bytes_be())),
43 calling_ap_invocation_identifier: Some(BigInt::from(201u32).to_signed_bytes_be()),
44 calling_ae_invocation_identifier: Some(BigInt::from(202u32).to_signed_bytes_be()),
45 implementation_information: Some("This Guy".into()),
46 },
47 AcseResponseInformation {
48 associate_result: AssociateResult::Accepted,
49 associate_source_diagnostic: AssociateSourceDiagnostic::User(AssociateSourceDiagnosticUserCategory::Null),
50 application_context_name: Oid::from(&[1, 0, 9506, 2, 1])?,
51 responding_ap_title: Some(ApTitle::Form2(Oid::from(&[1, 2, 3, 4, 5])?)),
52 responding_ae_qualifier: Some(AeQualifier::Form2(vec![100])),
53 responding_ap_invocation_identifier: Some(vec![101]),
54 responding_ae_invocation_identifier: Some(vec![102]),
55 implementation_information: Some("This Other Guy".into()),
56 },
57 vec![0xa8, 0x00],
58 vec![0xa9, 0x00],
59 )
60 .await?;
61
62 let (mut client_reader, mut client_writer) = client.split().await?;
63 let (mut server_reader, mut server_writer) = server.split().await?;
64
65 client_writer.send(vec![0xa0, 0x03, 0x02, 0x01, 0x01]).await?;
66 assert_eq!(AcseRecvResult::Data(vec![160, 3, 2, 1, 1]), server_reader.recv().await?);
67 server_writer.send(vec![0xa0, 0x03, 0x02, 0x01, 0x02]).await?;
68 assert_eq!(AcseRecvResult::Data(vec![160, 3, 2, 1, 2]), client_reader.recv().await?);
69
70 Ok(())
71 }
72
73 async fn create_acse_connection_pair_with_options(
74 reqeust_options: AcseRequestInformation,
75 response_options: AcseResponseInformation,
76 connect_data: Vec<u8>,
77 accept_data: Vec<u8>,
78 ) -> Result<(impl OsiSingleValueAcseConnection, impl OsiSingleValueAcseConnection), anyhow::Error> {
79 let test_address = "127.0.0.1:10002".parse()?;
81
82 let connect_information = CotpConnectInformation::default();
83
84 let client_path = async {
85 tokio::time::sleep(Duration::from_millis(1)).await; let tpkt_client = TcpTpktConnection::connect(test_address).await?;
87 let cotp_client = TcpCotpConnection::<TcpTpktReader, TcpTpktWriter>::initiate(tpkt_client, connect_information.clone()).await?;
88 let cosp_client = TcpCospInitiator::<TcpCotpReader<TcpTpktReader>, TcpCotpWriter<TcpTpktWriter>>::new(cotp_client, Default::default()).await?;
89 let copp_client = RustyCoppInitiatorIsoStack::<TcpTpktReader, TcpTpktWriter>::new(cosp_client, Default::default());
90 let acse_client = RustyOsiSingleValueAcseInitiatorIsoStack::<TcpTpktReader, TcpTpktWriter>::new(copp_client, reqeust_options.clone());
91 Ok(acse_client.initiate(Oid::from(&[1, 0, 9506, 2, 1]).map_err(|e| CoppError::InternalError(e.to_string()))?, connect_data.clone()).await?)
92 };
93 let server_path = async {
94 let tpkt_server = TcpTpktServer::listen(test_address).await?;
95 let (tpkt_connection, _) = tpkt_server.accept().await?;
96 let (cotp_server, _) = TcpCotpAcceptor::<TcpTpktReader, TcpTpktWriter>::new(tpkt_connection).await?;
97 let cotp_connection = cotp_server.accept(CotpAcceptInformation::default()).await?;
98 let (cosp_listener, _) = TcpCospListener::<TcpCotpReader<TcpTpktReader>, TcpCotpWriter<TcpTpktWriter>>::new(cotp_connection).await?;
99 let (copp_listener, _) =
100 RustyCoppListener::<TcpCospResponder<TcpCotpReader<TcpTpktReader>, TcpCotpWriter<TcpTpktWriter>>, TcpCospReader<TcpCotpReader<TcpTpktReader>>, TcpCospWriter<TcpCotpWriter<TcpTpktWriter>>>::new(cosp_listener).await?;
101 let (mut acse_listener, received_request_information) = RustyOsiSingleValueAcseListenerIsoStack::<TcpTpktReader, TcpTpktWriter>::new(copp_listener).await?;
102 acse_listener.set_response(Some(response_options.clone()));
103 let (acse_responder, received_connect_data) = acse_listener.responder().await?;
104
105 Ok((acse_responder.accept(accept_data.clone()).await?, received_request_information, received_connect_data))
106 };
107
108 let (copp_client, copp_server): (Result<_, anyhow::Error>, Result<_, anyhow::Error>) = join!(client_path, server_path);
109 let (copp_server, received_request_information, received_connect_data) = copp_server?;
110 let (copp_client, received_response_information, received_accept_data) = copp_client?;
111
112 assert_eq!(reqeust_options, received_request_information);
113 assert_eq!(connect_data, received_connect_data);
114 assert_eq!(response_options, received_response_information);
115 assert_eq!(accept_data, received_accept_data);
116
117 Ok((copp_client, copp_server))
118 }
119}