Skip to main content

rusty_copp/
service.rs

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                // resultant_contexts: None,
79            },
80            copp_information,
81        ))
82    }
83
84    // pub fn with_context(&mut self, resultant_contexts: Option<PresentationContextResultType>) {
85    //     self.resultant_contexts = resultant_contexts;
86    // }
87}
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}