Skip to main content

rusty_acse/
service.rs

1use std::marker::PhantomData;
2
3use der_parser::{
4    Oid,
5    ber::{BerObject, BerObjectContent, BitStringObject},
6    der::{Class, Header, Tag},
7};
8use rusty_copp::CoppConnection;
9use rusty_copp::{CoppError, CoppInitiator, CoppListener, CoppReader, CoppResponder, CoppWriter, PresentationContext, PresentationContextType, PresentationDataValueList, PresentationDataValues, UserData};
10
11use crate::{
12    AcseError, AcseRecvResult, AcseRequestInformation, AcseResponseInformation, AeQualifier, ApTitle, AssociateResult, AssociateSourceDiagnostic, AssociateSourceDiagnosticProviderCategory, AssociateSourceDiagnosticUserCategory,
13    OsiSingleValueAcseConnection, OsiSingleValueAcseInitiator, OsiSingleValueAcseListener, OsiSingleValueAcseReader, OsiSingleValueAcseResponder, OsiSingleValueAcseWriter,
14    messages::parsers::{process_request, process_response, to_acse_error},
15};
16
17pub struct RustyOsiSingleValueAcseInitiator<T: CoppInitiator, R: CoppReader, W: CoppWriter> {
18    copp_initiator: T,
19    copp_reader: PhantomData<R>,
20    copp_writer: PhantomData<W>,
21    options: AcseRequestInformation,
22}
23
24impl<T: CoppInitiator, R: CoppReader, W: CoppWriter> RustyOsiSingleValueAcseInitiator<T, R, W> {
25    pub fn new(copp_initiator: impl CoppInitiator, options: AcseRequestInformation) -> RustyOsiSingleValueAcseInitiator<impl CoppInitiator, impl CoppReader, impl CoppWriter> {
26        RustyOsiSingleValueAcseInitiator {
27            copp_initiator,
28            copp_reader: PhantomData::<R>,
29            copp_writer: PhantomData::<W>,
30            options,
31        }
32    }
33}
34
35impl<T: CoppInitiator, R: CoppReader, W: CoppWriter> OsiSingleValueAcseInitiator for RustyOsiSingleValueAcseInitiator<T, R, W> {
36    async fn initiate(self, abstract_syntax_name: Oid<'static>, user_data: Vec<u8>) -> Result<(impl OsiSingleValueAcseConnection, AcseResponseInformation, Vec<u8>), AcseError> {
37        let (copp_connection, received_user_data) = self
38            .copp_initiator
39            .initiate(
40                PresentationContextType::ContextDefinitionList(vec![
41                    // ACSE
42                    PresentationContext {
43                        indentifier: vec![1],
44                        abstract_syntax_name: Oid::from(&[2, 2, 1, 0, 1]).map_err(|e| CoppError::InternalError(e.to_string()))?,
45                        transfer_syntax_name_list: vec![Oid::from(&[2, 1, 1]).map_err(|e| CoppError::InternalError(e.to_string()))?],
46                    },
47                    // Requested BER Encoded Protocol
48                    PresentationContext {
49                        indentifier: vec![3],
50                        abstract_syntax_name: abstract_syntax_name,
51                        transfer_syntax_name_list: vec![Oid::from(&[2, 1, 1]).map_err(|e| CoppError::InternalError(e.to_string()))?],
52                    },
53                ]),
54                Some(UserData::FullyEncoded(vec![PresentationDataValueList {
55                    transfer_syntax_name: None,
56                    presentation_context_identifier: vec![0x01],
57                    presentation_data_values: PresentationDataValues::SingleAsn1Type(self.options.serialise(&Some(user_data))?),
58                }])),
59            )
60            .await?;
61        let (copp_reader, copp_writer) = copp_connection.split().await?;
62        let (acse_response, acse_response_data) = match received_user_data {
63            Some(UserData::FullyEncoded(pdvs)) => {
64                if pdvs.len() > 1 {
65                    return Err(AcseError::ProtocolError(format!("Expecting a single PDV on ACSE Response but found {}", pdvs.len())));
66                }
67                match pdvs.first() {
68                    Some(pdv) => {
69                        if pdv.presentation_context_identifier != vec![1] {
70                            return Err(AcseError::ProtocolError(format!("Expecting a context id of [1] on ACSE Response but found {:?}", pdv.presentation_context_identifier)));
71                        }
72                        match &pdv.presentation_data_values {
73                            PresentationDataValues::SingleAsn1Type(response_user_data) => process_response(response_user_data)?,
74                        }
75                    }
76                    None => return Err(AcseError::ProtocolError("No PDV was found on ACSE Response".into())),
77                }
78            }
79            None => return Err(AcseError::ProtocolError("No user data was found on ACSE Response".into())),
80        };
81        Ok((RustyAcseConnection { copp_reader, copp_writer }, acse_response, acse_response_data))
82    }
83}
84
85pub struct RustyOsiSingleValueAcseListener<T: CoppResponder, R: CoppReader, W: CoppWriter> {
86    copp_responder: T,
87    copp_reader: PhantomData<R>,
88    copp_writer: PhantomData<W>,
89    response: Option<AcseResponseInformation>,
90    acse_user_data: Vec<u8>,
91}
92
93impl<T: CoppResponder, R: CoppReader, W: CoppWriter> RustyOsiSingleValueAcseListener<T, R, W> {
94    pub async fn new(copp_listener: impl CoppListener) -> Result<(RustyOsiSingleValueAcseListener<impl CoppResponder, impl CoppReader, impl CoppWriter>, AcseRequestInformation), AcseError> {
95        let (copp_responder, copp_options) = copp_listener.responder().await?;
96        let copp_presentation_data_list = match copp_options {
97            Some(UserData::FullyEncoded(x)) => x,
98            None => return Err(AcseError::ProtocolError("COPP did not provide and data in the initiate payload".into())),
99        };
100        if copp_presentation_data_list.len() != 1 {
101            return Err(AcseError::ProtocolError(format!("Expected 1 COPP but found {}", copp_presentation_data_list.len())));
102        }
103        let copp_presentation_data = match copp_presentation_data_list.first() {
104            Some(x) => x,
105            None => return Err(AcseError::ProtocolError("Expected 1 COPP but did not find any".into())),
106        };
107        match &copp_presentation_data.transfer_syntax_name {
108            Some(x) if x == &Oid::from(&[2, 1, 1]).map_err(to_acse_error("Failed to parse BAR transfer syntax."))? => (),
109            Some(x) => return Err(AcseError::ProtocolError(format!("Unsupported transfer syntax: {}", x))),
110            None => (),
111        }
112        if copp_presentation_data.presentation_context_identifier != &[1] {
113            return Err(AcseError::ProtocolError(format!(
114                "Unexpected presentation contact id on COPP ACES Payload: Expecting &[1] but found {:?}",
115                copp_presentation_data.presentation_context_identifier
116            )));
117        }
118        let (request, acse_user_data) = match &copp_presentation_data.presentation_data_values {
119            PresentationDataValues::SingleAsn1Type(data) => process_request(data)?,
120        };
121        Ok((
122            RustyOsiSingleValueAcseListener {
123                copp_responder,
124                copp_reader: PhantomData::<R>,
125                copp_writer: PhantomData::<W>,
126                response: None,
127                acse_user_data,
128            },
129            request,
130        ))
131    }
132
133    pub fn set_response(&mut self, response: Option<AcseResponseInformation>) {
134        self.response = response;
135    }
136}
137
138impl<T: CoppResponder, R: CoppReader, W: CoppWriter> OsiSingleValueAcseListener for RustyOsiSingleValueAcseListener<T, R, W> {
139    async fn responder(self) -> Result<(impl OsiSingleValueAcseResponder, Vec<u8>), AcseError> {
140        match self.response {
141            Some(response) => Ok((RustyOsiSingleValueAcseResponder::<T, R, W>::new(self.copp_responder, response), self.acse_user_data)),
142            None => Err(AcseError::ProtocolError("No ACSE response information was provided".into())),
143        }
144    }
145}
146
147pub struct RustyOsiSingleValueAcseResponder<T: CoppResponder, R: CoppReader, W: CoppWriter> {
148    copp_responder: T,
149    copp_reader: PhantomData<R>,
150    copp_writer: PhantomData<W>,
151    response: AcseResponseInformation,
152}
153
154impl<T: CoppResponder, R: CoppReader, W: CoppWriter> RustyOsiSingleValueAcseResponder<T, R, W> {
155    pub fn new(copp_responder: T, response: AcseResponseInformation) -> Self {
156        RustyOsiSingleValueAcseResponder {
157            copp_responder,
158            copp_reader: PhantomData,
159            copp_writer: PhantomData,
160            response,
161        }
162    }
163}
164
165impl<T: CoppResponder, R: CoppReader, W: CoppWriter> OsiSingleValueAcseResponder for RustyOsiSingleValueAcseResponder<T, R, W> {
166    async fn accept(self, user_data: Vec<u8>) -> Result<impl OsiSingleValueAcseConnection, AcseError> {
167        let acse_data = self.response.serialise(&Some(user_data))?;
168        let copp_connection = self
169            .copp_responder
170            .accept(Some(UserData::FullyEncoded(vec![PresentationDataValueList {
171                transfer_syntax_name: None,
172                presentation_context_identifier: vec![1],
173                presentation_data_values: PresentationDataValues::SingleAsn1Type(acse_data),
174            }])))
175            .await?;
176        let (copp_reader, copp_writer) = copp_connection.split().await?;
177        Ok(RustyAcseConnection { copp_reader, copp_writer })
178    }
179}
180
181pub struct RustyAcseConnection<R: CoppReader, W: CoppWriter> {
182    copp_reader: R,
183    copp_writer: W,
184}
185
186impl<R: CoppReader, W: CoppWriter> OsiSingleValueAcseConnection for RustyAcseConnection<R, W> {
187    async fn split(self) -> Result<(impl OsiSingleValueAcseReader, impl OsiSingleValueAcseWriter), AcseError> {
188        Ok((RustyOsiSingleValueAcseReader::new(self.copp_reader), RustyOsiSingleValueAcseWriter::new(self.copp_writer)))
189    }
190}
191
192pub struct RustyOsiSingleValueAcseReader<R: CoppReader> {
193    copp_reader: R,
194}
195
196impl<R: CoppReader> RustyOsiSingleValueAcseReader<R> {
197    pub fn new(copp_reader: R) -> Self {
198        Self { copp_reader }
199    }
200}
201
202impl<R: CoppReader> OsiSingleValueAcseReader for RustyOsiSingleValueAcseReader<R> {
203    async fn recv(&mut self) -> Result<AcseRecvResult, AcseError> {
204        let copp_recv_result = self.copp_reader.recv().await?;
205        match copp_recv_result {
206            rusty_copp::CoppRecvResult::Closed => return Ok(AcseRecvResult::Closed),
207            rusty_copp::CoppRecvResult::Data(user_data) => match user_data {
208                UserData::FullyEncoded(presentation_data_value_lists) => {
209                    if presentation_data_value_lists.len() > 1 {
210                        return Err(AcseError::ProtocolError(format!("Expected one PDV value on ACSE read but found {}", presentation_data_value_lists.len())));
211                    }
212                    match presentation_data_value_lists.first() {
213                        Some(x) => {
214                            if x.presentation_context_identifier != vec![3] {
215                                return Err(AcseError::ProtocolError(format!("Expected a context id of 3 on ACSE read but was {:?}", x.presentation_context_identifier)));
216                            }
217                            match &x.presentation_data_values {
218                                PresentationDataValues::SingleAsn1Type(data) => return Ok(AcseRecvResult::Data(data.to_vec())),
219                            }
220                        }
221                        None => return Err(AcseError::ProtocolError("Expected one PDV value on ACSE read but did not find any".into())),
222                    }
223                }
224            },
225        }
226    }
227}
228
229pub struct RustyOsiSingleValueAcseWriter<W: CoppWriter> {
230    copp_writer: W,
231}
232
233impl<W: CoppWriter> RustyOsiSingleValueAcseWriter<W> {
234    pub fn new(copp_writer: W) -> Self {
235        Self { copp_writer }
236    }
237}
238
239impl<W: CoppWriter> OsiSingleValueAcseWriter for RustyOsiSingleValueAcseWriter<W> {
240    async fn send(&mut self, data: Vec<u8>) -> Result<(), AcseError> {
241        Ok(self
242            .copp_writer
243            .send(&UserData::FullyEncoded(vec![PresentationDataValueList {
244                transfer_syntax_name: None,
245                presentation_context_identifier: vec![3],
246                presentation_data_values: PresentationDataValues::SingleAsn1Type(data),
247            }]))
248            .await?)
249    }
250
251    async fn continue_send(&mut self) -> Result<(), AcseError> {
252        Ok(self.copp_writer.continue_send().await?)
253    }
254}
255
256impl AcseRequestInformation {
257    pub fn serialise(&self, user_data: &Option<Vec<u8>>) -> Result<Vec<u8>, AcseError> {
258        // There is a bug that prevents creating a tag with a value of 30. Instead we create the header from a raw tag.
259        // https://github.com/rusticata/der-parser/issues/89
260        let user_data_structure = user_data
261            .iter()
262            .map(|v| {
263                BerObject::from_header_and_content(
264                    Header::new(Class::ContextSpecific, true, Tag::from(0), der_parser::ber::Length::Definite(0)),
265                    der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
266                        Header::new(Class::Universal, true, Tag::from(8), der_parser::ber::Length::Definite(0)),
267                        der_parser::ber::BerObjectContent::Sequence(vec![
268                            BerObject::from_header_and_content(Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)), BerObjectContent::Integer(&[3])),
269                            BerObject::from_header_and_content(Header::new(Class::ContextSpecific, true, Tag::from(0), der_parser::ber::Length::Definite(0)), BerObjectContent::OctetString(v)),
270                        ]),
271                    )]),
272                )
273            })
274            .last();
275        let user_data_length = match &user_data_structure {
276            Some(x) => x.to_vec().map_err(to_acse_error("Failed to serialise ACSE Request User Data"))?.len(),
277            None => 0,
278        };
279
280        let payload = BerObject::from_header_and_content(
281            Header::new(Class::Application, true, Tag::from(0), der_parser::ber::Length::Definite(0)),
282            der_parser::ber::BerObjectContent::Sequence(
283                vec![
284                    // Version Default 1 - Not really needed, but we will put it anyway
285                    Some(BerObject::from_header_and_content(
286                        Header::new(Class::ContextSpecific, false, Tag::from(0), der_parser::ber::Length::Definite(0)),
287                        BerObjectContent::BitString(7, BitStringObject { data: &[0x80] }),
288                    )),
289                    // Application Context Name
290                    Some(BerObject::from_header_and_content(
291                        Header::new(Class::ContextSpecific, true, Tag::from(1), der_parser::ber::Length::Definite(0)),
292                        der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
293                            Header::new(Class::Universal, false, Tag::Oid, der_parser::ber::Length::Definite(0)),
294                            BerObjectContent::OID(self.application_context_name.clone()),
295                        )]),
296                    )),
297                    // Called AP Title
298                    self.called_ap_title
299                        .iter()
300                        .map(|ap_title| {
301                            BerObject::from_header_and_content(
302                                Header::new(Class::ContextSpecific, true, Tag::from(2), der_parser::ber::Length::Definite(0)),
303                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
304                                    Header::new(Class::Universal, false, Tag::Oid, der_parser::ber::Length::Definite(0)),
305                                    BerObjectContent::OID(match ap_title {
306                                        ApTitle::Form2(oid) => oid.to_owned(),
307                                    }),
308                                )]),
309                            )
310                        })
311                        .last(),
312                    // Called AE Qualifier
313                    self.called_ae_qualifier
314                        .iter()
315                        .map(|ae_qualifier| {
316                            BerObject::from_header_and_content(
317                                Header::new(Class::ContextSpecific, true, Tag::from(3), der_parser::ber::Length::Definite(0)),
318                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
319                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
320                                    BerObjectContent::Integer(match ae_qualifier {
321                                        AeQualifier::Form2(value) => value,
322                                    }),
323                                )]),
324                            )
325                        })
326                        .last(),
327                    // Called AP InvocationIdentifier
328                    self.called_ap_invocation_identifier
329                        .iter()
330                        .map(|ap_invocation_id| {
331                            BerObject::from_header_and_content(
332                                Header::new(Class::ContextSpecific, true, Tag::from(4), der_parser::ber::Length::Definite(0)),
333                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
334                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
335                                    BerObjectContent::Integer(ap_invocation_id),
336                                )]),
337                            )
338                        })
339                        .last(),
340                    // Called AE InvocationIdentifier
341                    self.called_ae_invocation_identifier
342                        .iter()
343                        .map(|ae_invocation_id| {
344                            BerObject::from_header_and_content(
345                                Header::new(Class::ContextSpecific, true, Tag::from(5), der_parser::ber::Length::Definite(0)),
346                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
347                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
348                                    BerObjectContent::Integer(ae_invocation_id),
349                                )]),
350                            )
351                        })
352                        .last(),
353                    // Calling AP Title
354                    self.calling_ap_title
355                        .iter()
356                        .map(|ap_title| {
357                            BerObject::from_header_and_content(
358                                Header::new(Class::ContextSpecific, true, Tag::from(6), der_parser::ber::Length::Definite(0)),
359                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
360                                    Header::new(Class::Universal, false, Tag::Oid, der_parser::ber::Length::Definite(0)),
361                                    BerObjectContent::OID(match ap_title {
362                                        ApTitle::Form2(oid) => oid.to_owned(),
363                                    }),
364                                )]),
365                            )
366                        })
367                        .last(),
368                    // Calling AE Qualifier
369                    self.calling_ae_qualifier
370                        .iter()
371                        .map(|ae_qualifier| {
372                            BerObject::from_header_and_content(
373                                Header::new(Class::ContextSpecific, true, Tag::from(7), der_parser::ber::Length::Definite(0)),
374                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
375                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
376                                    BerObjectContent::Integer(match ae_qualifier {
377                                        AeQualifier::Form2(value) => value,
378                                    }),
379                                )]),
380                            )
381                        })
382                        .last(),
383                    // Calling AP InvocationIdentifier
384                    self.calling_ap_invocation_identifier
385                        .iter()
386                        .map(|ap_invocation_id| {
387                            BerObject::from_header_and_content(
388                                Header::new(Class::ContextSpecific, true, Tag::from(8), der_parser::ber::Length::Definite(0)),
389                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
390                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
391                                    BerObjectContent::Integer(ap_invocation_id),
392                                )]),
393                            )
394                        })
395                        .last(),
396                    // Calling AE InvocationIdentifier
397                    self.calling_ae_invocation_identifier
398                        .iter()
399                        .map(|ae_invocation_id| {
400                            BerObject::from_header_and_content(
401                                Header::new(Class::ContextSpecific, true, Tag::from(9), der_parser::ber::Length::Definite(0)),
402                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
403                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
404                                    BerObjectContent::Integer(ae_invocation_id),
405                                )]),
406                            )
407                        })
408                        .last(),
409                    // Implementation Information
410                    self.implementation_information
411                        .iter()
412                        .map(|implementation_information| {
413                            BerObject::from_header_and_content(
414                                Header::new(Class::ContextSpecific, false, Tag::from(29), der_parser::ber::Length::Definite(0)),
415                                BerObjectContent::GraphicString(implementation_information),
416                            )
417                        })
418                        .last(),
419                    // User Information
420                    user_data_structure,
421                ]
422                .iter()
423                .filter_map(|v| v.to_owned())
424                .collect(),
425            ),
426        );
427        let mut data = payload.to_vec().map_err(to_acse_error("Failed to serialise Application Request Information"))?;
428        let tl = data.len();
429        if user_data_length > 0 {
430            data[tl - user_data_length] = 0xbe;
431        }
432        Ok(data)
433    }
434}
435
436impl AcseResponseInformation {
437    pub fn serialise(&self, user_data: &Option<Vec<u8>>) -> Result<Vec<u8>, AcseError> {
438        // There is a bug that prevents creating a tag with a value of 30. Instead we create the header from a raw tag.
439        // https://github.com/rusticata/der-parser/issues/89
440        let user_data_structure = user_data
441            .iter()
442            .map(|v| {
443                BerObject::from_header_and_content(
444                    Header::new(Class::ContextSpecific, true, Tag::from(0), der_parser::ber::Length::Definite(0)),
445                    der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
446                        Header::new(Class::Universal, true, Tag::from(8), der_parser::ber::Length::Definite(0)),
447                        der_parser::ber::BerObjectContent::Sequence(vec![
448                            BerObject::from_header_and_content(Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)), BerObjectContent::Integer(&[3])),
449                            BerObject::from_header_and_content(Header::new(Class::ContextSpecific, true, Tag::from(0), der_parser::ber::Length::Definite(0)), BerObjectContent::OctetString(v)),
450                        ]),
451                    )]),
452                )
453            })
454            .last();
455        let user_data_length = match &user_data_structure {
456            Some(x) => x.to_vec().map_err(to_acse_error("Failed to serialise ACSE Request User Data"))?.len(),
457            None => 0,
458        };
459
460        let payload = BerObject::from_header_and_content(
461            Header::new(Class::Application, true, Tag::from(1), der_parser::ber::Length::Definite(0)),
462            der_parser::ber::BerObjectContent::Sequence(
463                vec![
464                    // Version Default 1 - No need to specify
465                    // Application Context Name
466                    Some(BerObject::from_header_and_content(
467                        Header::new(Class::ContextSpecific, true, Tag::from(1), der_parser::ber::Length::Definite(0)),
468                        der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
469                            Header::new(Class::Universal, false, Tag::Oid, der_parser::ber::Length::Definite(0)),
470                            BerObjectContent::OID(self.application_context_name.clone()),
471                        )]),
472                    )),
473                    // Result
474                    Some(BerObject::from_header_and_content(
475                        Header::new(Class::ContextSpecific, true, Tag::from(2), der_parser::ber::Length::Definite(0)),
476                        der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
477                            Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
478                            match &self.associate_result {
479                                AssociateResult::Accepted => BerObjectContent::Integer(&[0]),
480                                AssociateResult::RejectedPermanent => BerObjectContent::Integer(&[1]),
481                                AssociateResult::RejectedTransient => BerObjectContent::Integer(&[2]),
482                                AssociateResult::Unknown(x) => BerObjectContent::Integer(&x),
483                            },
484                        )]),
485                    )),
486                    // Result Diagnostic
487                    Some(BerObject::from_header_and_content(
488                        Header::new(Class::ContextSpecific, true, Tag::from(3), der_parser::ber::Length::Definite(0)),
489                        der_parser::ber::BerObjectContent::Sequence(vec![match &self.associate_source_diagnostic {
490                            AssociateSourceDiagnostic::User(category) => BerObject::from_header_and_content(
491                                Header::new(Class::ContextSpecific, true, Tag::from(1), der_parser::ber::Length::Definite(0)),
492                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
493                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
494                                    der_parser::ber::BerObjectContent::Integer(match category {
495                                        AssociateSourceDiagnosticUserCategory::Null => &[0],
496                                        AssociateSourceDiagnosticUserCategory::NoReasonGiven => &[1],
497                                        AssociateSourceDiagnosticUserCategory::ApplicationContextNameNotSupported => &[2],
498                                        AssociateSourceDiagnosticUserCategory::CallingApTitleNotRecognized => &[3],
499                                        AssociateSourceDiagnosticUserCategory::CallingApInvocationIdentifierNotRecognized => &[4],
500                                        AssociateSourceDiagnosticUserCategory::CallingAeQualifierNotRecognized => &[5],
501                                        AssociateSourceDiagnosticUserCategory::CallingAeInvocationIdentifierNotRecognized => &[6],
502                                        AssociateSourceDiagnosticUserCategory::CalledApTitleNotRecognized => &[7],
503                                        AssociateSourceDiagnosticUserCategory::CalledApInvocationIdentifierNotRecognized => &[8],
504                                        AssociateSourceDiagnosticUserCategory::CalledAeQualifierNotRecognized => &[9],
505                                        AssociateSourceDiagnosticUserCategory::CalledAeInvocationIdentifierNotRecognized => &[10],
506                                        AssociateSourceDiagnosticUserCategory::AuthenticationMechanismNameNotRecognized => &[11],
507                                        AssociateSourceDiagnosticUserCategory::AuthenticationMechanismNameRequired => &[12],
508                                        AssociateSourceDiagnosticUserCategory::AuthenticationFailure => &[13],
509                                        AssociateSourceDiagnosticUserCategory::AuthenticationRequired => &[14],
510                                        AssociateSourceDiagnosticUserCategory::Unknown(value) => &value,
511                                    }),
512                                )]),
513                            ),
514                            AssociateSourceDiagnostic::Provider(category) => BerObject::from_header_and_content(
515                                Header::new(Class::ContextSpecific, true, Tag::from(1), der_parser::ber::Length::Definite(0)),
516                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
517                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
518                                    der_parser::ber::BerObjectContent::Integer(match category {
519                                        AssociateSourceDiagnosticProviderCategory::Null => &[0],
520                                        AssociateSourceDiagnosticProviderCategory::NoReasonGiven => &[1],
521                                        AssociateSourceDiagnosticProviderCategory::NoCommonAcseVersion => &[2],
522                                        AssociateSourceDiagnosticProviderCategory::Unknown(value) => &value,
523                                    }),
524                                )]),
525                            ),
526                            AssociateSourceDiagnostic::Unknown(_) => return Err(AcseError::InternalError("Cannot serialise Unknown diagnostic on ACSE Response".into())),
527                        }]),
528                    )),
529                    // Called AP Title
530                    self.responding_ap_title
531                        .iter()
532                        .map(|ap_title| {
533                            BerObject::from_header_and_content(
534                                Header::new(Class::ContextSpecific, true, Tag::from(4), der_parser::ber::Length::Definite(0)),
535                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
536                                    Header::new(Class::Universal, false, Tag::Oid, der_parser::ber::Length::Definite(0)),
537                                    BerObjectContent::OID(match ap_title {
538                                        ApTitle::Form2(oid) => oid.to_owned(),
539                                    }),
540                                )]),
541                            )
542                        })
543                        .last(),
544                    // Called AE Qualifier
545                    self.responding_ae_qualifier
546                        .iter()
547                        .map(|ae_qualifier| {
548                            BerObject::from_header_and_content(
549                                Header::new(Class::ContextSpecific, true, Tag::from(5), der_parser::ber::Length::Definite(0)),
550                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
551                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
552                                    BerObjectContent::Integer(match ae_qualifier {
553                                        AeQualifier::Form2(value) => value,
554                                    }),
555                                )]),
556                            )
557                        })
558                        .last(),
559                    // Called AP InvocationIdentifier
560                    self.responding_ap_invocation_identifier
561                        .iter()
562                        .map(|ap_invocation_id| {
563                            BerObject::from_header_and_content(
564                                Header::new(Class::ContextSpecific, true, Tag::from(6), der_parser::ber::Length::Definite(0)),
565                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
566                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
567                                    BerObjectContent::Integer(ap_invocation_id),
568                                )]),
569                            )
570                        })
571                        .last(),
572                    // Called AE InvocationIdentifier
573                    self.responding_ae_invocation_identifier
574                        .iter()
575                        .map(|ae_invocation_id| {
576                            BerObject::from_header_and_content(
577                                Header::new(Class::ContextSpecific, true, Tag::from(7), der_parser::ber::Length::Definite(0)),
578                                der_parser::ber::BerObjectContent::Sequence(vec![BerObject::from_header_and_content(
579                                    Header::new(Class::Universal, false, Tag::Integer, der_parser::ber::Length::Definite(0)),
580                                    BerObjectContent::Integer(ae_invocation_id),
581                                )]),
582                            )
583                        })
584                        .last(),
585                    // Implementation Information
586                    self.implementation_information
587                        .iter()
588                        .map(|implementation_information| {
589                            BerObject::from_header_and_content(
590                                Header::new(Class::ContextSpecific, false, Tag::from(29), der_parser::ber::Length::Definite(0)),
591                                BerObjectContent::GraphicString(implementation_information),
592                            )
593                        })
594                        .last(),
595                    // User Information
596                    user_data_structure,
597                ]
598                .iter()
599                .filter_map(|v| v.to_owned())
600                .collect(),
601            ),
602        );
603        let mut data = payload.to_vec().map_err(to_acse_error("Failed to serialise Application Request Information"))?;
604        let tl = data.len();
605        if user_data_length > 0 {
606            data[tl - user_data_length] = 0xbe;
607        }
608        Ok(data)
609    }
610}