1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
use crate::TransportError;
use ockam_core::compat::{boxed::Box, vec::Vec};
use ockam_core::{async_trait, Address, Encodable, Result, TransportMessage, TransportType};
/// Generic representation of a Transport
/// At minimum, a Transport must be able
/// - return its type
/// - instantiate workers for all the addresses with that transport type in a Route
pub const MAXIMUM_MESSAGE_LENGTH: usize = u16::MAX as usize;
#[async_trait]
pub trait Transport: Send + Sync + 'static {
/// Return the type of the Transport
fn transport_type(&self) -> TransportType;
/// Instantiate transport workers for in order to communicate with a remote address
/// and return the local address of the transport worker
async fn resolve_address(&self, address: Address) -> Result<Address>;
/// Stop all workers and free all resources associated with the connection
async fn disconnect(&self, address: Address) -> Result<()>;
}
/// Helper that creates a length-prefixed buffer containing the given
/// `TransportMessage`'s payload
///
/// The length-prefix is encoded as a big-endian 16-bit unsigned
/// integer.
pub fn encode_transport_message(msg: TransportMessage) -> Result<Vec<u8>> {
let mut msg_buf = msg.encode().map_err(|_| TransportError::SendBadMessage)?;
if msg_buf.len() > MAXIMUM_MESSAGE_LENGTH {
Err(TransportError::Capacity)?;
}
// Create a buffer that includes the message length in big endian
let mut len = (msg_buf.len() as u16).to_be_bytes().to_vec();
// Fun fact: reversing a vector in place, appending the length,
// and then reversing it again is faster for large message sizes
// than adding the large chunk of data.
//
// https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=8669a640004ac85c7be38b19e3e73dcb
msg_buf.reverse();
len.reverse();
msg_buf.append(&mut len);
msg_buf.reverse();
Ok(msg_buf)
}
#[cfg(test)]
mod test {
use super::{encode_transport_message, TransportMessage};
use ockam_core::route;
#[test]
fn prepare_message_should_discard_large_messages() {
let msg = TransportMessage::v1(route![], route![], vec![0; u16::MAX as usize + 1]);
let result = encode_transport_message(msg);
assert!(result.is_err());
}
}