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 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 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 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 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 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 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 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 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 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 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 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 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 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 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_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 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 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 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 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 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 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 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 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 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_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}