1use std::marker::PhantomData;
2
3use der_parser::Oid;
4use rusty_cosp::{CospConnection, CospInitiator, CospListener, CospReader, CospResponder, CospWriter};
5
6use crate::{
7 CoppConnection, CoppConnectionInformation, CoppError, CoppInitiator, CoppListener, CoppReader, CoppRecvResult, CoppResponder, CoppWriter, PresentationContextResult, PresentationContextResultCause, PresentationContextResultType,
8 PresentationContextType, UserData,
9 messages::{accept::AcceptMessage, connect::ConnectMessage},
10};
11
12pub struct RustyCoppInitiator<T: CospInitiator, R: CospReader, W: CospWriter> {
13 cosp_initiator: T,
14 cosp_reader: PhantomData<R>,
15 cosp_writer: PhantomData<W>,
16 options: CoppConnectionInformation,
17}
18
19impl<T: CospInitiator, R: CospReader, W: CospWriter> RustyCoppInitiator<T, R, W> {
20 pub fn new(cosp_initiator: impl CospInitiator, options: CoppConnectionInformation) -> RustyCoppInitiator<impl CospInitiator, impl CospReader, impl CospWriter> {
21 RustyCoppInitiator {
22 cosp_initiator,
23 cosp_reader: PhantomData::<R>,
24 cosp_writer: PhantomData::<W>,
25 options,
26 }
27 }
28}
29
30impl<T: CospInitiator, R: CospReader, W: CospWriter> CoppInitiator for RustyCoppInitiator<T, R, W> {
31 async fn initiate(self, presentation_contexts: PresentationContextType, user_data: Option<UserData>) -> Result<(impl CoppConnection, Option<UserData>), CoppError> {
32 let cosp_initiator = self.cosp_initiator;
33
34 let connect_message = ConnectMessage::new(None, self.options.calling_presentation_selector, self.options.called_presentation_selector, presentation_contexts, user_data);
35 let data = connect_message.serialise()?;
36
37 let (cosp_connection, accept_data) = cosp_initiator.initiate(Some(data)).await?;
38 let accept_message = match accept_data {
39 Some(data) => AcceptMessage::parse(data)?,
40 None => return Err(CoppError::ProtocolError("No accept message data was received fromt he remote host.".to_string())),
41 };
42
43 let (cosp_reader, cosp_writer) = cosp_connection.split().await?;
44 Ok((RustyCoppConnection::new(cosp_reader, cosp_writer), accept_message.user_data()))
45 }
46}
47
48pub struct RustyCoppListener<T: CospResponder, R: CospReader, W: CospWriter> {
49 cosp_responder: T,
50 user_data: Option<UserData>,
51 cosp_reader: PhantomData<R>,
52 cosp_writer: PhantomData<W>,
53 connection_information: CoppConnectionInformation,
54}
55
56impl<T: CospResponder, R: CospReader, W: CospWriter> RustyCoppListener<T, R, W> {
57 pub async fn new(cosp_listener: impl CospListener) -> Result<(RustyCoppListener<impl CospResponder, impl CospReader, impl CospWriter>, CoppConnectionInformation), CoppError> {
58 let (cosp_responder, _, user_data) = cosp_listener.responder().await?;
59
60 let mut connect_message = match user_data {
61 Some(user_data) => ConnectMessage::parse(&user_data)?,
62 None => return Err(CoppError::ProtocolError("No presentation connection data received.".to_string())),
63 };
64
65 let presentation_user_data = connect_message.user_data_mut().take();
66 let copp_information = CoppConnectionInformation {
67 calling_presentation_selector: connect_message.calling_presentation_selector().cloned(),
68 called_presentation_selector: connect_message.called_presentation_selector().cloned(),
69 };
70
71 Ok((
72 RustyCoppListener {
73 cosp_responder,
74 cosp_reader: PhantomData::<R>,
75 cosp_writer: PhantomData::<W>,
76 user_data: presentation_user_data,
77 connection_information: copp_information.clone(),
78 },
80 copp_information,
81 ))
82 }
83
84 }
88
89impl<T: CospResponder, R: CospReader, W: CospWriter> CoppListener for RustyCoppListener<T, R, W> {
90 async fn responder(self) -> Result<(impl CoppResponder, Option<UserData>), CoppError> {
91 Ok((RustyCoppResponder::<T, R, W>::new(self.cosp_responder, self.connection_information), self.user_data))
92 }
93}
94
95pub struct RustyCoppResponder<T: CospResponder, R: CospReader, W: CospWriter> {
96 cosp_responder: T,
97 cosp_reader: PhantomData<R>,
98 cosp_writer: PhantomData<W>,
99 connection_information: CoppConnectionInformation,
100}
101
102impl<T: CospResponder, R: CospReader, W: CospWriter> RustyCoppResponder<T, R, W> {
103 fn new(cosp_responder: T, connection_information: CoppConnectionInformation) -> RustyCoppResponder<impl CospResponder, impl CospReader, impl CospWriter> {
104 RustyCoppResponder {
105 cosp_responder,
106 cosp_reader: PhantomData::<R>,
107 cosp_writer: PhantomData::<W>,
108 connection_information,
109 }
110 }
111}
112
113impl<T: CospResponder, R: CospReader, W: CospWriter> CoppResponder for RustyCoppResponder<T, R, W> {
114 async fn accept(self, accept_data: Option<UserData>) -> Result<impl CoppConnection, CoppError> {
115 let contexts = PresentationContextResultType::ContextDefinitionList(vec![
116 PresentationContextResult {
117 result: PresentationContextResultCause::Acceptance,
118 transfer_syntax_name: Some(Oid::from(&[2, 1, 1]).map_err(|e| CoppError::InternalError(e.to_string()))?),
119 provider_reason: None,
120 },
121 PresentationContextResult {
122 result: PresentationContextResultCause::Acceptance,
123 transfer_syntax_name: Some(Oid::from(&[2, 1, 1]).map_err(|e| CoppError::InternalError(e.to_string()))?),
124 provider_reason: None,
125 },
126 ]);
127
128 let responder = self.cosp_responder;
129 let accept_message = AcceptMessage::new(None, self.connection_information.called_presentation_selector, contexts, accept_data);
130 let accept_message_data = Some(accept_message.serialise()?);
131 let (cosp_reader, cosp_writer) = responder.accept(accept_message_data).await?.split().await?;
132 Ok(RustyCoppConnection::new(cosp_reader, cosp_writer))
133 }
134}
135
136pub struct RustyCoppConnection<R: CospReader, W: CospWriter> {
137 cosp_reader: R,
138 cosp_writer: W,
139}
140
141impl<R: CospReader, W: CospWriter> RustyCoppConnection<R, W> {
142 fn new(cosp_reader: R, cosp_writer: W) -> RustyCoppConnection<impl CospReader, impl CospWriter> {
143 RustyCoppConnection { cosp_reader, cosp_writer }
144 }
145}
146
147impl<R: CospReader, W: CospWriter> CoppConnection for RustyCoppConnection<R, W> {
148 async fn split(self) -> Result<(impl CoppReader, impl CoppWriter), CoppError> {
149 Ok((RustyCoppReader::new(self.cosp_reader), RustyCoppWriter::new(self.cosp_writer)))
150 }
151}
152
153pub struct RustyCoppReader<R: CospReader> {
154 cosp_reader: R,
155}
156
157impl<R: CospReader> RustyCoppReader<R> {
158 fn new(cosp_reader: R) -> RustyCoppReader<impl CospReader> {
159 RustyCoppReader { cosp_reader }
160 }
161}
162
163impl<R: CospReader> CoppReader for RustyCoppReader<R> {
164 async fn recv(&mut self) -> Result<CoppRecvResult, CoppError> {
165 match self.cosp_reader.recv().await? {
166 rusty_cosp::CospRecvResult::Closed => return Ok(CoppRecvResult::Closed),
167 rusty_cosp::CospRecvResult::Data(items) => Ok(CoppRecvResult::Data(UserData::parse_raw(&items).map_err(|e| CoppError::ProtocolError(e.to_string()))?)),
168 }
169 }
170}
171
172pub struct RustyCoppWriter<W: CospWriter> {
173 cosp_writer: W,
174}
175
176impl<W: CospWriter> RustyCoppWriter<W> {
177 fn new(cosp_writer: W) -> RustyCoppWriter<impl CospWriter> {
178 RustyCoppWriter { cosp_writer }
179 }
180}
181
182impl<W: CospWriter> CoppWriter for RustyCoppWriter<W> {
183 async fn send(&mut self, user_data: &UserData) -> Result<(), CoppError> {
184 self.cosp_writer
185 .send(user_data.to_ber().to_vec().map_err(|e| CoppError::ProtocolError(e.to_string()))?.as_slice())
186 .await
187 .map_err(|e| CoppError::ProtocolStackError(e))
188 }
189
190 async fn continue_send(&mut self) -> Result<(), CoppError> {
191 Ok(self.cosp_writer.continue_send().await?)
192 }
193}