Skip to main content

rusty_cotp/
api.rs

1use std::collections::VecDeque;
2
3use rusty_tpkt::{ProtocolInformation, TpktError};
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum CotpError {
8    /// Indicates issues with parsing of incoming packets or protocol violations with input user data.
9    #[error("COTP Protocol Error - {}", .0)]
10    ProtocolError(String),
11
12    /// Indicates issues with lower layers.
13    #[error("COTP over TPKT Protocol Stack Error - {}", .0)]
14    ProtocolStackError(#[from] TpktError),
15
16    /// Indicates issues with the underlying TCP socket or hardware.
17    #[error("COTP IO Error: {:?}", .0)]
18    IoError(#[from] std::io::Error),
19
20    /// Usually indicates a bug or an unhandled error condition.
21    #[error("COTP Error: {}", .0)]
22    InternalError(String),
23}
24
25/// Captures information about a COTP connection allowing it to be used later for connection negotiation.
26#[derive(PartialEq, Clone, Debug)]
27pub struct CotpProtocolInformation {
28    initiator_reference: u16,
29    responder_reference: u16,
30    calling_tsap_id: Option<Vec<u8>>,
31    called_tsap_id: Option<Vec<u8>>,
32}
33
34impl CotpProtocolInformation {
35    pub(crate) fn new(initiator_reference: u16, responder_reference: u16, calling_tsap_id: Option<Vec<u8>>, called_tsap_id: Option<Vec<u8>>) -> Self {
36        CotpProtocolInformation { initiator_reference, responder_reference, calling_tsap_id, called_tsap_id }
37    }
38
39    /// Used to specify information used by the COTP service during the initiator phase. This generates a random initiator and set the responder reference to 0.
40    pub fn initiator(calling_tsap_id: Option<Vec<u8>>, called_tsap_id: Option<Vec<u8>>) -> Self {
41        CotpProtocolInformation { initiator_reference: rand::random(), responder_reference: 0, calling_tsap_id, called_tsap_id }
42    }
43
44    /// Convert initiator information received by a connection request to responder information. This generates a random responder reference.
45    pub fn responder(self) -> Self {
46        CotpProtocolInformation { initiator_reference: self.initiator_reference, responder_reference: rand::random(), calling_tsap_id: self.calling_tsap_id.clone(), called_tsap_id: self.calling_tsap_id.clone() }
47    }
48
49    pub fn initiator_reference(&self) -> u16 {
50        self.initiator_reference
51    }
52
53    /// This will be 0 for information received from the initiator.
54    pub fn responder_reference(&self) -> u16 {
55        self.responder_reference
56    }
57
58    pub fn calling_tsap_id(&self) -> Option<&Vec<u8>> {
59        self.calling_tsap_id.as_ref()
60    }
61
62    pub fn called_tsap_id(&self) -> Option<&Vec<u8>> {
63        self.called_tsap_id.as_ref()
64    }
65}
66
67impl ProtocolInformation for CotpProtocolInformation {}
68
69/// Provides a mechnism to respond with negotiated values suring the connect phase.
70pub trait CotpResponder: Send {
71    /// Accepts a connection with the given parameters.
72    fn accept(self, options: CotpProtocolInformation) -> impl std::future::Future<Output = Result<impl CotpConnection, CotpError>> + Send;
73}
74
75/// A trait representing a COTP connection.
76pub trait CotpConnection: Send {
77    /// Gets the information regarding the protocols that have been negotiated during the connect phase.
78    fn get_protocol_infomation_list(&self) -> &Vec<Box<dyn ProtocolInformation>>;
79
80    /// Splits a connection into reader and writer components. This must be done before the connection is used.
81    fn split(self) -> impl std::future::Future<Output = Result<(impl CotpReader, impl CotpWriter), CotpError>> + Send;
82}
83
84pub trait CotpReader: Send {
85    /// Reads from a COTP connection. There are three outcomes.
86    /// * Some(data) - Data was read.
87    /// * None - The underlying connection was closed normally.
88    /// * TpktError - May indicate a packet was malformed, there was an IO error or some other internal failure occurred.
89    /// 
90    /// This operation is cancel safe.
91    fn recv(&mut self) -> impl std::future::Future<Output = Result<Option<Vec<u8>>, CotpError>> + Send;
92}
93
94pub trait CotpWriter: Send {
95    /// Writes to a COTP connection. This uses a VedDeque as a buffer. This is to ensure the operation is cancel safe so long as the buffer is not dropped while it has data.
96    /// 
97    /// This operation is cancel safe as long as the data in the input buffer is not dropped.
98    /// The Veque is intended to be used as a FIFO buffer stored on the caller and reused.
99    fn send(&mut self, input: &mut VecDeque<Vec<u8>>) -> impl std::future::Future<Output = Result<(), CotpError>> + Send;
100}