Skip to main content

rusty_cosp/
lib.rs

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    // TODO Need to fix Accept
103    // TODO Need to take into account the mtu of the peer
104    // TODO Need to DT a lot bigger data
105    #[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    // TODO verify connect info
171    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 test_address = "127.0.0.1:10002".parse()?;
174
175        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}