1mod api;
2mod message;
3mod packet;
4mod service;
5
6use rusty_cotp::TcpCotpReader;
7use rusty_cotp::TcpCotpWriter;
8
9pub use crate::api::*;
10pub use crate::service::*;
11
12pub type RustyCospReaderIsoStack<R> = TcpCospReader<TcpCotpReader<R>>;
13pub type RustyCospWriterIsoStack<W> = TcpCospWriter<TcpCotpWriter<W>>;
14pub type RustyCospInitiatorIsoStack<R, W> = TcpCospInitiator<TcpCotpReader<R>, TcpCotpWriter<W>>;
15pub type RustyCospListenerIsoStack<R, W> = TcpCospListener<TcpCotpReader<R>, TcpCotpWriter<W>>;
16pub type RustyCospResponderIsoStack<R, W> = TcpCospResponder<TcpCotpReader<R>, TcpCotpWriter<W>>;
17pub type RustyCospConnectionIsoStack<R, W> = TcpCospConnection<TcpCotpReader<R>, TcpCotpWriter<W>>;
18
19#[cfg(test)]
20mod tests {
21 use std::ops::Range;
22
23 use rusty_cotp::{CotpAcceptInformation, CotpConnectInformation, CotpResponder, TcpCotpAcceptor, TcpCotpConnection, TcpCotpReader, TcpCotpWriter};
24 use rusty_tpkt::{TcpTpktConnection, TcpTpktReader, TcpTpktServer, TcpTpktWriter};
25 use tokio::join;
26 use tracing_test::traced_test;
27
28 use super::*;
29
30 #[tokio::test]
31 #[traced_test]
32 async fn it_should_negotiate_a_version_2_unlimited_size_connection() -> Result<(), anyhow::Error> {
33 let (client_connection, server_connection) = create_cosp_connection_pair_with_options(None, CospConnectionInformation::default(), None).await?;
34
35 let (mut client_reader, mut client_writer) = client_connection.split().await?;
36 let (mut server_reader, mut server_writer) = server_connection.split().await?;
37
38 client_writer.send(&[0x61, 0x02, 0x05, 0x00]).await?;
39 match server_reader.recv().await? {
40 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
41 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "61020500"),
42 }
43 server_writer.send(&[1, 2, 3, 4]).await?;
44 match client_reader.recv().await? {
45 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
46 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "01020304"),
47 }
48
49 Ok(())
50 }
51
52 #[tokio::test]
53 #[traced_test]
54 async fn it_should_pass_small_connect_and_accept_data() -> Result<(), anyhow::Error> {
55 let (client_connection, server_connection) = create_cosp_connection_pair_with_options(Some(&[5, 6, 7]), CospConnectionInformation::default(), Some(vec![5, 4, 3])).await?;
56
57 let (mut client_reader, mut client_writer) = client_connection.split().await?;
58 let (mut server_reader, mut server_writer) = server_connection.split().await?;
59
60 client_writer.send(&[0x61, 0x02, 0x05, 0x00]).await?;
61 match server_reader.recv().await? {
62 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
63 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "61020500"),
64 }
65 server_writer.send(&[1, 2, 3, 4]).await?;
66 match client_reader.recv().await? {
67 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
68 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "01020304"),
69 }
70
71 Ok(())
72 }
73
74 #[tokio::test]
75 #[traced_test]
76 async fn it_should_pass_medium_connect_and_accept_data() -> Result<(), anyhow::Error> {
77 let mut initial_connect_data = vec![0xabu8; 10240];
78 rand::fill(initial_connect_data.as_mut_slice());
79
80 let mut init_accept_data = vec![0x8; 65510];
81 rand::fill(init_accept_data.as_mut_slice());
82
83 let (client_connection, server_connection) = create_cosp_connection_pair_with_options(Some(initial_connect_data.as_slice()), CospConnectionInformation::default(), Some(init_accept_data)).await?;
84
85 let (mut client_reader, mut client_writer) = client_connection.split().await?;
86 let (mut server_reader, mut server_writer) = server_connection.split().await?;
87
88 client_writer.send(&[0x61, 0x02, 0x05, 0x00]).await?;
89 match server_reader.recv().await? {
90 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
91 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "61020500"),
92 }
93 server_writer.send(&[1, 2, 3, 4]).await?;
94 match client_reader.recv().await? {
95 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
96 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "01020304"),
97 }
98
99 Ok(())
100 }
101
102 #[tokio::test]
106 #[traced_test]
107 async fn it_should_pass_jumbo_connect_and_accept_data() -> Result<(), anyhow::Error> {
108 let mut initial_connect_data = vec![0x00u8; 10240 + 65520 + 65520 + 100];
109 rand::fill(initial_connect_data.as_mut_slice());
110
111 let mut init_accept_data = vec![0x00u8; 65510 + 65510 + 100];
112 rand::fill(init_accept_data.as_mut_slice());
113
114 let (client_connection, server_connection) = create_cosp_connection_pair_with_options(Some(initial_connect_data.as_slice()), CospConnectionInformation::default(), Some(init_accept_data)).await?;
115
116 let (mut client_reader, mut client_writer) = client_connection.split().await?;
117 let (mut server_reader, mut server_writer) = server_connection.split().await?;
118
119 client_writer.send(&[0x61, 0x02, 0x05, 0x00]).await?;
120 match server_reader.recv().await? {
121 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
122 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "61020500"),
123 }
124 server_writer.send(&[1, 2, 3, 4]).await?;
125 match client_reader.recv().await? {
126 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
127 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "01020304"),
128 }
129
130 Ok(())
131 }
132
133 #[tokio::test]
134 #[traced_test]
135 async fn it_should_pass_and_honour_options() -> Result<(), anyhow::Error> {
136 let mut initial_connect_data = vec![0x00u8; 10240 + 65520 + 65520 + 100];
137 rand::fill(initial_connect_data.as_mut_slice());
138
139 let mut init_accept_data = vec![0x00u8; 65510 + 65510 + 100];
140 rand::fill(init_accept_data.as_mut_slice());
141
142 let (client_connection, server_connection) = create_cosp_connection_pair_with_options(
143 Some(initial_connect_data.as_slice()),
144 CospConnectionInformation {
145 tsdu_maximum_size: Some(512),
146 calling_session_selector: Some(vec![0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]),
147 called_session_selector: Some(vec![0xcb, 0xa9, 0x87, 0x65, 0x43, 0x21]),
148 },
149 Some(init_accept_data),
150 )
151 .await?;
152
153 let (mut client_reader, mut client_writer) = client_connection.split().await?;
154 let (mut server_reader, mut server_writer) = server_connection.split().await?;
155
156 client_writer.send(&[0x61, 0x02, 0x05, 0x00]).await?;
157 match server_reader.recv().await? {
158 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
159 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "61020500"),
160 }
161 server_writer.send(&[1, 2, 3, 4]).await?;
162 match client_reader.recv().await? {
163 CospRecvResult::Closed => assert!(false, "Expected the connection to be open."),
164 CospRecvResult::Data(data) => assert_eq!(hex::encode(data), "01020304"),
165 }
166
167 Ok(())
168 }
169
170 async fn create_cosp_connection_pair_with_options(connect_data: Option<&[u8]>, options: CospConnectionInformation, accept_data: Option<Vec<u8>>) -> Result<(impl CospConnection, impl CospConnection), anyhow::Error> {
172 let test_address = format!("127.0.0.1:{}", rand::random_range::<u16, Range<u16>>(20000..30000)).parse()?;
173 let connect_information = CotpConnectInformation::default();
176
177 let tpkt_listener = TcpTpktServer::listen(test_address).await?;
178 let (tpkt_client, tpkt_server) = join!(TcpTpktConnection::connect(test_address), tpkt_listener.accept());
179
180 let (cotp_initiator, cotp_acceptor) = join!(async { TcpCotpConnection::<TcpTpktReader, TcpTpktWriter>::initiate(tpkt_client?, connect_information.clone()).await }, async {
181 let (acceptor, remote) = TcpCotpAcceptor::<TcpTpktReader, TcpTpktWriter>::new(tpkt_server?.0).await?;
182 assert_eq!(remote, connect_information);
183 acceptor.accept(CotpAcceptInformation::default()).await
184 });
185
186 let cotp_client = cotp_initiator?;
187 let cotp_server = cotp_acceptor?;
188 let cosp_client_connector = TcpCospInitiator::<TcpCotpReader<TcpTpktReader>, TcpCotpWriter<TcpTpktWriter>>::new(cotp_client, options.clone()).await?;
189
190 let (cosp_client, cosp_server) = join!(async { cosp_client_connector.initiate(connect_data.map(|o| o.to_vec())).await }, async {
191 let (cosp_server_connector, _) = RustyCospListenerIsoStack::<TcpTpktReader, TcpTpktWriter>::new(cotp_server).await?;
192 let (acceptor, connection_information, user_data) = cosp_server_connector.responder().await?;
193 assert_eq!(connect_data.map(|x| x.to_vec()), user_data);
194 assert_eq!(connection_information.called_session_selector, options.called_session_selector);
195 acceptor.accept(accept_data).await
196 });
197
198 Ok((cosp_client?.0, cosp_server?))
199 }
200}