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/// Provides a set of parameters used to tune timers or prevent the runaway consumption or resources due to a malicious client.
26#[derive(PartialEq, Clone, Debug)]
27pub struct CotpConnectionParameters {
28 /// A limit on the reassembled payload. If this is exceeded, an error will be raised on the read operation.
29 ///
30 /// Defaults to 1MB for payload plus a 1024 byte overhead to account for headers. Only applies to inbound data.
31 pub max_reassembled_payload_size: usize,
32}
33
34impl Default for CotpConnectionParameters {
35 fn default() -> Self {
36 Self { max_reassembled_payload_size: 1048576 + 1024 }
37 }
38}
39
40/// Captures information about a COTP connection allowing it to be used later for connection negotiation.
41#[derive(PartialEq, Clone, Debug)]
42pub struct CotpProtocolInformation {
43 initiator_reference: u16,
44 responder_reference: u16,
45 calling_tsap_id: Option<Vec<u8>>,
46 called_tsap_id: Option<Vec<u8>>,
47}
48
49impl CotpProtocolInformation {
50 pub(crate) fn new(initiator_reference: u16, responder_reference: u16, calling_tsap_id: Option<Vec<u8>>, called_tsap_id: Option<Vec<u8>>) -> Self {
51 CotpProtocolInformation { initiator_reference, responder_reference, calling_tsap_id, called_tsap_id }
52 }
53
54 /// 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.
55 pub fn initiator(calling_tsap_id: Option<Vec<u8>>, called_tsap_id: Option<Vec<u8>>) -> Self {
56 CotpProtocolInformation { initiator_reference: rand::random(), responder_reference: 0, calling_tsap_id, called_tsap_id }
57 }
58
59 /// Convert initiator information received by a connection request to responder information. This generates a random responder reference.
60 pub fn responder(self) -> Self {
61 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() }
62 }
63
64 /// The initiator reference. As this supports Class 0 only, the reference is informational.
65 pub fn initiator_reference(&self) -> u16 {
66 self.initiator_reference
67 }
68
69 /// The responder reference. As this supports Class 0 only, the reference is informational.
70 ///
71 /// This will be 0 for information received from the initiator.
72 pub fn responder_reference(&self) -> u16 {
73 self.responder_reference
74 }
75
76 /// The Transport Id of the caller. Similar to a TCP port except it is not ephemeral for the calling party.
77 pub fn calling_tsap_id(&self) -> Option<&Vec<u8>> {
78 self.calling_tsap_id.as_ref()
79 }
80
81 /// The Transport Id of the called host. Similar to a TCP port.
82 pub fn called_tsap_id(&self) -> Option<&Vec<u8>> {
83 self.called_tsap_id.as_ref()
84 }
85}
86
87impl ProtocolInformation for CotpProtocolInformation {}
88
89/// Provides a mechnism to respond with negotiated values suring the connect phase.
90pub trait CotpResponder: Send {
91 /// Accepts a connection with the given parameters.
92 ///
93 /// This the CotpResponder is dropped the connection will be closed.
94 fn accept(self, options: CotpProtocolInformation) -> impl std::future::Future<Output = Result<impl CotpConnection, CotpError>> + Send;
95}
96
97/// A trait representing a COTP connection.
98pub trait CotpConnection: Send {
99 /// Gets the information regarding the protocols that have been negotiated during the connect phase.
100 fn get_protocol_infomation_list(&self) -> &Vec<Box<dyn ProtocolInformation>>;
101
102 /// Splits a connection into reader and writer components. This must be done before the connection is used.
103 fn split(self) -> impl std::future::Future<Output = Result<(impl CotpReader, impl CotpWriter), CotpError>> + Send;
104}
105
106/// A trait representing the read half of COTP connection.
107pub trait CotpReader: Send {
108 /// Reads from a COTP connection. There are three outcomes.
109 /// * Some(data) - Data was read.
110 /// * None - The underlying connection was closed normally.
111 /// * TpktError - May indicate a packet was malformed, there was an IO error or some other internal failure occurred.
112 ///
113 /// This operation is cancel safe.
114 fn recv(&mut self) -> impl std::future::Future<Output = Result<Option<Vec<u8>>, CotpError>> + Send;
115}
116
117/// A trait representing the write half of COTP connection.
118pub trait CotpWriter: Send {
119 /// 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.
120 ///
121 /// This operation is cancel safe as long as the data in the input buffer is not dropped.
122 /// The Veque is intended to be used as a FIFO buffer stored on the caller and reused.
123 fn send(&mut self, input: &mut VecDeque<Vec<u8>>) -> impl std::future::Future<Output = Result<(), CotpError>> + Send;
124}