[WIP] Security work While on holiday
This commit is contained in:
parent
a81ac4efca
commit
7f0231e3f1
109 changed files with 19694 additions and 5210 deletions
|
|
@ -1,7 +1,7 @@
|
|||
use crate::ConnectionHandle;
|
||||
#[cfg(feature = "pipes")]
|
||||
use crate::pipe::PipeReader;
|
||||
use mtp_codec::CommunicationValue;
|
||||
use mtp_codec::{CommunicationValue, DecodeLimits, TypeMap};
|
||||
use mtp_common::CommunicationError;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
|
@ -148,6 +148,7 @@ pub struct Sender {
|
|||
handle: Arc<ConnectionHandle>,
|
||||
connection: Connection,
|
||||
policy: Arc<Policy>,
|
||||
type_map: Arc<RwLock<TypeMap>>,
|
||||
}
|
||||
|
||||
impl Sender {
|
||||
|
|
@ -158,9 +159,15 @@ impl Sender {
|
|||
handle,
|
||||
connection,
|
||||
policy,
|
||||
type_map: Arc::new(RwLock::new(TypeMap::latest())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Bind control frames created by this sender to the negotiated protocol map.
|
||||
pub async fn set_type_map(&self, type_map: &TypeMap) {
|
||||
*self.type_map.write().await = type_map.clone();
|
||||
}
|
||||
|
||||
#[instrument(skip(stream, data, policy), level = "trace")]
|
||||
async fn write_frame(
|
||||
stream: &mut wtransport::SendStream,
|
||||
|
|
@ -174,9 +181,7 @@ impl Sender {
|
|||
return Err(CommunicationError::MessageTooLarge);
|
||||
}
|
||||
|
||||
let len_bytes = (bytes.len() as u32).to_be_bytes();
|
||||
let write_result = async {
|
||||
stream.write_all(&len_bytes).await?;
|
||||
stream.write_all(&bytes).await?;
|
||||
Ok::<(), wtransport::error::StreamWriteError>(())
|
||||
};
|
||||
|
|
@ -458,12 +463,16 @@ impl Sender {
|
|||
|
||||
let mut stream = Self::open_uni_stream(&self.connection, &self.policy).await?;
|
||||
|
||||
let request = CommunicationValue::new(mtp_codec::CommunicationType::PipeRequest)
|
||||
.with_id(pipe_id)
|
||||
.add_typed_default(
|
||||
mtp_codec::DataType::Description,
|
||||
mtp_codec::DataValue::Str(description.to_string()),
|
||||
);
|
||||
let type_map = self.type_map.read().await.clone();
|
||||
let request = CommunicationValue::new_with_type_map(
|
||||
mtp_codec::CommunicationType::PipeRequest,
|
||||
&type_map,
|
||||
)
|
||||
.with_id(pipe_id)
|
||||
.add_typed_default(
|
||||
mtp_codec::DataType::Description,
|
||||
mtp_codec::DataValue::Str(description.to_string()),
|
||||
);
|
||||
|
||||
Self::write_frame(&mut stream, &request, &self.policy).await?;
|
||||
|
||||
|
|
@ -595,6 +604,7 @@ struct ReceiverInner {
|
|||
ping_control: Arc<RwLock<PingControl>>,
|
||||
queue_notify: Arc<Notify>,
|
||||
max_message_size: Arc<AtomicU64>,
|
||||
type_map: Arc<RwLock<TypeMap>>,
|
||||
}
|
||||
|
||||
impl Clone for Receiver {
|
||||
|
|
@ -624,6 +634,7 @@ impl Receiver {
|
|||
Self::new_with_max_message_size(connection, handle, policy.clone(), policy.max_message_size)
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub(crate) fn new_for_handshake(
|
||||
connection: Connection,
|
||||
handle: Arc<ConnectionHandle>,
|
||||
|
|
@ -661,6 +672,8 @@ impl Receiver {
|
|||
let accept_queue_notify = queue_notify.clone();
|
||||
let max_message_size = Arc::new(AtomicU64::new(initial_max_message_size));
|
||||
let accept_max_message_size = max_message_size.clone();
|
||||
let type_map = Arc::new(RwLock::new(TypeMap::latest()));
|
||||
let accept_type_map = type_map.clone();
|
||||
let stream_limit = Arc::new(Semaphore::new(policy.max_concurrent_stream_tasks.max(1)));
|
||||
let accept_stream_limit = stream_limit.clone();
|
||||
debug!(
|
||||
|
|
@ -728,6 +741,7 @@ impl Receiver {
|
|||
let stream_policy = accept_policy.clone();
|
||||
let stream_ping_control = accept_ping_control.clone();
|
||||
let stream_max_message_size = accept_max_message_size.clone();
|
||||
let stream_type_map = accept_type_map.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let _permit = permit;
|
||||
|
|
@ -748,18 +762,25 @@ impl Receiver {
|
|||
|
||||
let frame_limit = stream_max_message_size.load(Ordering::Relaxed);
|
||||
match Self::read_one_frame(&mut s, &stream_policy, frame_limit).await {
|
||||
Ok(ReceivedFrame::Message(msg)) => {
|
||||
Ok(ReceivedFrame::Message(mut msg)) => {
|
||||
let negotiated_type_map =
|
||||
stream_type_map.read().await.clone();
|
||||
msg.set_type_map(&negotiated_type_map);
|
||||
frame_count += 1;
|
||||
|
||||
#[cfg(feature = "pipes")]
|
||||
{
|
||||
let pipe_request_type =
|
||||
mtp_codec::CommunicationType::PipeRequest
|
||||
.try_to_id(&mtp_codec::TypeMap::latest());
|
||||
if Some(msg.get_type()) == pipe_request_type
|
||||
if msg.is_type(mtp_codec::CommunicationType::PipeRequest)
|
||||
&& frame_count == 1
|
||||
{
|
||||
let pipe_id = msg.get_id();
|
||||
let Some(pipe_id) = msg.id().filter(|id| *id != 0) else {
|
||||
let error = CommunicationError::Other(
|
||||
"PipeRequest frame must contain a non-zero id".into(),
|
||||
);
|
||||
let _ = msg_tx_stream.send(Err(error.clone())).await;
|
||||
stream_handle.close(Some(error));
|
||||
break;
|
||||
};
|
||||
let description = msg
|
||||
.get_str(mtp_codec::DataType::Description)
|
||||
.unwrap_or("")
|
||||
|
|
@ -784,18 +805,14 @@ impl Receiver {
|
|||
}
|
||||
}
|
||||
|
||||
let ping_type = mtp_codec::CommunicationType::Ping
|
||||
.try_to_id(&mtp_codec::TypeMap::latest());
|
||||
let pong_type = mtp_codec::CommunicationType::Pong
|
||||
.try_to_id(&mtp_codec::TypeMap::latest());
|
||||
let control = {
|
||||
let control = stream_ping_control.read().await;
|
||||
if Some(msg.get_type()) == ping_type {
|
||||
if msg.is_type(mtp_codec::CommunicationType::Ping) {
|
||||
control
|
||||
.pong_sender
|
||||
.clone()
|
||||
.map(|sender| (Some(sender), None))
|
||||
} else if Some(msg.get_type()) == pong_type {
|
||||
} else if msg.is_type(mtp_codec::CommunicationType::Pong) {
|
||||
control
|
||||
.pong_observer
|
||||
.clone()
|
||||
|
|
@ -806,9 +823,16 @@ impl Receiver {
|
|||
};
|
||||
|
||||
if let Some((Some(sender), _)) = control {
|
||||
let mut pong = CommunicationValue::new(mtp_codec::CommunicationType::Pong)
|
||||
.with_id(msg.get_id());
|
||||
if let Some(timestamp) = msg.get_data_opt(mtp_codec::DataType::Timestamp) {
|
||||
let mut pong = CommunicationValue::new_with_type_map(
|
||||
mtp_codec::CommunicationType::Pong,
|
||||
&negotiated_type_map,
|
||||
);
|
||||
if let Some(id) = msg.id() {
|
||||
pong = pong.with_id(id);
|
||||
} else {
|
||||
pong = pong.without_id();
|
||||
}
|
||||
if let Some(timestamp) = msg.get_data(mtp_codec::DataType::Timestamp) {
|
||||
pong = pong.add_typed_default(
|
||||
mtp_codec::DataType::Timestamp,
|
||||
timestamp.clone(),
|
||||
|
|
@ -917,6 +941,7 @@ impl Receiver {
|
|||
ping_control,
|
||||
queue_notify,
|
||||
max_message_size,
|
||||
type_map,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -928,6 +953,11 @@ impl Receiver {
|
|||
.store(max_message_size, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Bind subsequently decoded frames to the negotiated protocol version.
|
||||
pub async fn set_type_map(&self, type_map: &TypeMap) {
|
||||
*self.inner.type_map.write().await = type_map.clone();
|
||||
}
|
||||
|
||||
/* Respond to reserved Ping frames without exposing them to application I/O. */
|
||||
pub fn respond_to_pings(&self, sender: Sender) {
|
||||
if let Ok(mut control) = self.inner.ping_control.try_write() {
|
||||
|
|
@ -982,18 +1012,21 @@ impl Receiver {
|
|||
return Ok(ReceivedFrame::ClosedByPeer);
|
||||
}
|
||||
|
||||
let len_usize = len as usize;
|
||||
if len as u64 > max_message_size {
|
||||
let body_len = len as usize;
|
||||
let frame_len = body_len
|
||||
.checked_add(4)
|
||||
.ok_or(CommunicationError::MessageTooLarge)?;
|
||||
if frame_len as u64 > max_message_size {
|
||||
return Err(CommunicationError::MessageTooLarge);
|
||||
}
|
||||
|
||||
// Grow in bounded chunks instead of trusting the peer's length prefix
|
||||
// enough to allocate the complete frame up front.
|
||||
let mut buf = Vec::new();
|
||||
buf.try_reserve(len_usize.min(16 * 1024))
|
||||
buf.try_reserve(body_len.min(16 * 1024))
|
||||
.map_err(|_| CommunicationError::MessageTooLarge)?;
|
||||
while buf.len() < len_usize {
|
||||
let chunk_len = (len_usize - buf.len()).min(16 * 1024);
|
||||
while buf.len() < body_len {
|
||||
let chunk_len = (body_len - buf.len()).min(16 * 1024);
|
||||
let mut chunk = [0u8; 16 * 1024];
|
||||
match timeout(
|
||||
policy.read_timeout,
|
||||
|
|
@ -1008,7 +1041,7 @@ impl Receiver {
|
|||
}
|
||||
Ok(Err(StreamReadExactError::FinishedEarly(n))) => {
|
||||
warn!(
|
||||
"[Receiver] body read ended early ({}/{len_usize} bytes): stream closed by peer",
|
||||
"[Receiver] body read ended early ({}/{body_len} bytes): stream closed by peer",
|
||||
buf.len() + n
|
||||
);
|
||||
return Err(CommunicationError::StreamError);
|
||||
|
|
@ -1024,14 +1057,20 @@ impl Receiver {
|
|||
return Err(CommunicationError::StreamError);
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("[Receiver] body read timed out (len={len_usize})");
|
||||
warn!("[Receiver] body read timed out (len={body_len})");
|
||||
return Err(CommunicationError::StreamError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let message = CommunicationValue::from_bytes(&buf)
|
||||
.map_err(|_| CommunicationError::ParseCommunicationValue)?;
|
||||
let mut frame = Vec::with_capacity(frame_len);
|
||||
frame.extend_from_slice(&len_buf);
|
||||
frame.extend_from_slice(&buf);
|
||||
let message = CommunicationValue::from_bytes_with_limits(
|
||||
&frame,
|
||||
DecodeLimits::for_transport_message_size(max_message_size),
|
||||
)
|
||||
.map_err(|_| CommunicationError::ParseCommunicationValue)?;
|
||||
|
||||
Ok(ReceivedFrame::Message(message))
|
||||
}
|
||||
|
|
|
|||
1512
transport/src/encrypted_pipe.rs
Normal file
1512
transport/src/encrypted_pipe.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,11 @@ use crate::{Policy, TransportSendStream};
|
|||
use mtp_codec::CommunicationValue;
|
||||
use mtp_common::CommunicationError;
|
||||
|
||||
/// Writes the canonical length-prefixed MTP frame used by every transport.
|
||||
/// Writes the canonical self-framed MTP value used by every transport.
|
||||
///
|
||||
/// `CommunicationValue` already begins with the four-byte body length. The
|
||||
/// transport writes that representation directly so a frame does not carry a
|
||||
/// redundant outer length prefix.
|
||||
pub(crate) async fn write_frame<S: TransportSendStream>(
|
||||
stream: &mut S,
|
||||
value: &CommunicationValue,
|
||||
|
|
@ -14,8 +18,70 @@ pub(crate) async fn write_frame<S: TransportSendStream>(
|
|||
{
|
||||
return Err(CommunicationError::MessageTooLarge);
|
||||
}
|
||||
stream
|
||||
.write_all(&(bytes.len() as u32).to_be_bytes())
|
||||
.await?;
|
||||
stream.write_all(&bytes).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use async_trait::async_trait;
|
||||
use mtp_codec::{CommunicationType, DataValue};
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use tokio::io::AsyncWrite;
|
||||
|
||||
#[derive(Default)]
|
||||
struct BufferStream {
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
impl AsyncWrite for BufferStream {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
_cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<std::io::Result<usize>> {
|
||||
self.bytes.extend_from_slice(buf);
|
||||
Poll::Ready(Ok(buf.len()))
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl TransportSendStream for BufferStream {
|
||||
async fn write_all(&mut self, buf: &[u8]) -> Result<(), CommunicationError> {
|
||||
self.bytes.extend_from_slice(buf);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn finish(&mut self) -> Result<(), CommunicationError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn framing_preserves_a_generic_payload() {
|
||||
let payload = DataValue::Array(vec![
|
||||
DataValue::Str("payload".into()),
|
||||
DataValue::Bytes(vec![1, 2, 3]),
|
||||
]);
|
||||
let frame = CommunicationValue::new(CommunicationType::Pong).with_payload(payload.clone());
|
||||
let mut stream = BufferStream::default();
|
||||
|
||||
write_frame(&mut stream, &frame, &Policy::default())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let body_len = u32::from_be_bytes(stream.bytes[..4].try_into().unwrap()) as usize;
|
||||
assert_eq!(body_len, stream.bytes.len() - 4);
|
||||
let decoded = CommunicationValue::from_bytes(&stream.bytes).unwrap();
|
||||
assert_eq!(decoded.into_payload(), payload);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
use crate::{
|
||||
Policy, TransportConnection, TransportRecvStream, TransportSendStream, framing::write_frame,
|
||||
};
|
||||
use mtp_codec::CommunicationValue;
|
||||
use mtp_codec::{CommunicationValue, DecodeLimits, TypeMap};
|
||||
use mtp_common::CommunicationError;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
|
@ -22,6 +22,7 @@ pub struct GenericSender<C: TransportConnection> {
|
|||
policy: Arc<Policy>,
|
||||
persistent: Arc<Mutex<Option<C::SendStream>>>,
|
||||
send_lock: Arc<Mutex<()>>,
|
||||
type_map: Arc<RwLock<TypeMap>>,
|
||||
}
|
||||
|
||||
impl<C: TransportConnection> Clone for GenericSender<C> {
|
||||
|
|
@ -31,6 +32,7 @@ impl<C: TransportConnection> Clone for GenericSender<C> {
|
|||
policy: self.policy.clone(),
|
||||
persistent: self.persistent.clone(),
|
||||
send_lock: self.send_lock.clone(),
|
||||
type_map: self.type_map.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,9 +44,15 @@ impl<C: TransportConnection> GenericSender<C> {
|
|||
policy,
|
||||
persistent: Arc::new(Mutex::new(None)),
|
||||
send_lock: Arc::new(Mutex::new(())),
|
||||
type_map: Arc::new(RwLock::new(TypeMap::latest())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Bind control frames created by this sender to the negotiated protocol map.
|
||||
pub async fn set_type_map(&self, type_map: &TypeMap) {
|
||||
*self.type_map.write().await = type_map.clone();
|
||||
}
|
||||
|
||||
async fn open(&self) -> Result<C::SendStream, CommunicationError> {
|
||||
timeout(self.policy.open_stream_timeout, self.connection.open_uni())
|
||||
.await
|
||||
|
|
@ -112,12 +120,16 @@ impl<C: TransportConnection> GenericSender<C> {
|
|||
|
||||
let mut stream = self.open().await?;
|
||||
|
||||
let request = CommunicationValue::new(mtp_codec::CommunicationType::PipeRequest)
|
||||
.with_id(pipe_id)
|
||||
.add_typed_default(
|
||||
mtp_codec::DataType::Description,
|
||||
mtp_codec::DataValue::Str(description.to_string()),
|
||||
);
|
||||
let type_map = self.type_map.read().await.clone();
|
||||
let request = CommunicationValue::new_with_type_map(
|
||||
mtp_codec::CommunicationType::PipeRequest,
|
||||
&type_map,
|
||||
)
|
||||
.with_id(pipe_id)
|
||||
.add_typed_default(
|
||||
mtp_codec::DataType::Description,
|
||||
mtp_codec::DataValue::Str(description.to_string()),
|
||||
);
|
||||
|
||||
timeout(
|
||||
self.policy.write_timeout,
|
||||
|
|
@ -166,6 +178,7 @@ pub struct GenericReceiver<C: TransportConnection> {
|
|||
connection: C,
|
||||
ping_sender: Arc<RwLock<Option<GenericSender<C>>>>,
|
||||
max_message_size: Arc<AtomicU64>,
|
||||
type_map: Arc<RwLock<TypeMap>>,
|
||||
_accept_task: Arc<tokio::task::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
|
|
@ -178,6 +191,7 @@ impl<C: TransportConnection> Clone for GenericReceiver<C> {
|
|||
connection: self.connection.clone(),
|
||||
ping_sender: self.ping_sender.clone(),
|
||||
max_message_size: self.max_message_size.clone(),
|
||||
type_map: self.type_map.clone(),
|
||||
_accept_task: self._accept_task.clone(),
|
||||
}
|
||||
}
|
||||
|
|
@ -206,6 +220,8 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
let task_connection = connection.clone();
|
||||
let task_policy = policy.clone();
|
||||
let task_max_message_size = max_message_size.clone();
|
||||
let type_map = Arc::new(RwLock::new(TypeMap::latest()));
|
||||
let task_type_map = type_map.clone();
|
||||
let task_accept_task_tx = tx.clone();
|
||||
#[cfg(feature = "pipes")]
|
||||
let task_accept_task_pipe_tx = pipe_tx.clone();
|
||||
|
|
@ -260,6 +276,7 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
let max_message_size = task_max_message_size.clone();
|
||||
let ping_sender = task_ping_sender.clone();
|
||||
let connection = task_connection.clone();
|
||||
let type_map = task_type_map.clone();
|
||||
tokio::spawn(async move {
|
||||
let _permit = permit;
|
||||
let mut stream = stream;
|
||||
|
|
@ -298,13 +315,22 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
break;
|
||||
}
|
||||
let frame_limit = max_message_size.load(Ordering::Relaxed);
|
||||
if len as u64 > frame_limit {
|
||||
tracing::warn!(len, "MTP receive stream frame is too large");
|
||||
let body_len = len as usize;
|
||||
let frame_len = match body_len.checked_add(4) {
|
||||
Some(frame_len) => frame_len,
|
||||
None => {
|
||||
let _ = tx.send(Err(CommunicationError::MessageTooLarge)).await;
|
||||
connection.close(policy.application_close_code, b"frame too large");
|
||||
break;
|
||||
}
|
||||
};
|
||||
if frame_len as u64 > frame_limit {
|
||||
tracing::warn!(frame_len, "MTP receive stream frame is too large");
|
||||
let _ = tx.send(Err(CommunicationError::MessageTooLarge)).await;
|
||||
connection.close(policy.application_close_code, b"frame too large");
|
||||
break;
|
||||
}
|
||||
let target_len = len as usize;
|
||||
let target_len = body_len;
|
||||
let mut body = Vec::new();
|
||||
if body.try_reserve(target_len.min(16 * 1024)).is_err() {
|
||||
tracing::warn!(
|
||||
|
|
@ -343,7 +369,13 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
break;
|
||||
}
|
||||
frames += 1;
|
||||
let message = match CommunicationValue::from_bytes(&body) {
|
||||
let mut frame = Vec::with_capacity(frame_len);
|
||||
frame.extend_from_slice(&len.to_be_bytes());
|
||||
frame.extend_from_slice(&body);
|
||||
let mut message = match CommunicationValue::from_bytes_with_limits(
|
||||
&frame,
|
||||
DecodeLimits::for_transport_message_size(frame_limit),
|
||||
) {
|
||||
Ok(message) => message,
|
||||
Err(_) => {
|
||||
tracing::warn!("MTP receive stream contained an invalid frame");
|
||||
|
|
@ -354,13 +386,25 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
break;
|
||||
}
|
||||
};
|
||||
let negotiated_type_map = type_map.read().await.clone();
|
||||
message.set_type_map(&negotiated_type_map);
|
||||
|
||||
#[cfg(feature = "pipes")]
|
||||
{
|
||||
let pipe_request_type = mtp_codec::CommunicationType::PipeRequest
|
||||
.try_to_id(&mtp_codec::TypeMap::latest());
|
||||
if Some(message.get_type()) == pipe_request_type && frames == 1 {
|
||||
let pipe_id = message.get_id();
|
||||
if message.is_type(mtp_codec::CommunicationType::PipeRequest)
|
||||
&& frames == 1
|
||||
{
|
||||
let Some(pipe_id) = message.id().filter(|id| *id != 0) else {
|
||||
let error = CommunicationError::Other(
|
||||
"PipeRequest frame must contain a non-zero id".into(),
|
||||
);
|
||||
let _ = tx.send(Err(error.clone())).await;
|
||||
connection.close(
|
||||
policy.application_close_code,
|
||||
b"pipe request missing id",
|
||||
);
|
||||
break;
|
||||
};
|
||||
let description = message
|
||||
.get_str(mtp_codec::DataType::Description)
|
||||
.unwrap_or("")
|
||||
|
|
@ -383,11 +427,17 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
|
||||
if message.is_type(mtp_codec::CommunicationType::Ping) {
|
||||
if let Some(sender) = ping_sender.read().await.clone() {
|
||||
let mut pong =
|
||||
CommunicationValue::new(mtp_codec::CommunicationType::Pong)
|
||||
.with_id(message.get_id());
|
||||
let mut pong = CommunicationValue::new_with_type_map(
|
||||
mtp_codec::CommunicationType::Pong,
|
||||
&negotiated_type_map,
|
||||
);
|
||||
if let Some(id) = message.id() {
|
||||
pong = pong.with_id(id);
|
||||
} else {
|
||||
pong = pong.without_id();
|
||||
}
|
||||
if let Some(timestamp) =
|
||||
message.get_data_opt(mtp_codec::DataType::Timestamp)
|
||||
message.get_data(mtp_codec::DataType::Timestamp)
|
||||
{
|
||||
pong = pong.add_typed_default(
|
||||
mtp_codec::DataType::Timestamp,
|
||||
|
|
@ -412,6 +462,7 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
connection,
|
||||
ping_sender,
|
||||
max_message_size,
|
||||
type_map,
|
||||
_accept_task: Arc::new(accept_task),
|
||||
}
|
||||
}
|
||||
|
|
@ -424,6 +475,11 @@ impl<C: TransportConnection> GenericReceiver<C> {
|
|||
self.max_message_size
|
||||
.store(max_message_size, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Bind subsequently decoded frames to the negotiated protocol version.
|
||||
pub async fn set_type_map(&self, type_map: &TypeMap) {
|
||||
*self.type_map.write().await = type_map.clone();
|
||||
}
|
||||
pub async fn receive(&self) -> Result<CommunicationValue, CommunicationError> {
|
||||
self.incoming
|
||||
.lock()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ pub mod generic_connection;
|
|||
pub mod pinning;
|
||||
pub mod transport_traits;
|
||||
|
||||
#[cfg(feature = "pipes")]
|
||||
pub mod encrypted_pipe;
|
||||
#[cfg(feature = "pipes")]
|
||||
pub mod pipe;
|
||||
|
||||
|
|
@ -15,6 +17,15 @@ pub use generic_connection::{GenericReceiver, GenericSender};
|
|||
#[cfg(feature = "pipes")]
|
||||
pub use connection::TransportEvent;
|
||||
#[cfg(feature = "pipes")]
|
||||
pub use encrypted_pipe::{
|
||||
EncryptedPipeError, EncryptedPipeReader, EncryptedPipeWriter, MAX_ENCRYPTED_PIPE_RECORD,
|
||||
MAX_PIPE_SESSION_OFFER, PIPE_SESSION_ENCRYPTION_PURPOSE, PIPE_SESSION_SIGNATURE_PURPOSE,
|
||||
PipeProtectionContext, PipeSessionError, PipeSessionParameters,
|
||||
accept_forward_secure_pipe_session, accept_forward_secure_pipe_session_with_key_history,
|
||||
accept_pipe_session, accept_pipe_session_with_key_history, accept_pipe_session_with_policy,
|
||||
initiate_forward_secure_pipe_session, initiate_group_pipe_session, initiate_pipe_session,
|
||||
};
|
||||
#[cfg(feature = "pipes")]
|
||||
pub use pipe::{PipeReader, PipeWriter};
|
||||
|
||||
pub use client::{ClientConfig, connect, connect_with_config};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ impl PipeWriter {
|
|||
}
|
||||
|
||||
impl<S: tokio::io::AsyncWrite + Send + Unpin> PipeWriter<S> {
|
||||
pub fn into_inner(self) -> S {
|
||||
self.stream
|
||||
}
|
||||
|
||||
pub async fn finish_async(mut self) -> Result<(), mtp_common::CommunicationError> {
|
||||
tokio::io::AsyncWriteExt::shutdown(&mut self)
|
||||
.await
|
||||
|
|
@ -58,6 +62,10 @@ pub struct PipeReader<R = wtransport::RecvStream> {
|
|||
}
|
||||
|
||||
impl<R> PipeReader<R> {
|
||||
pub fn into_inner(self) -> R {
|
||||
self.stream
|
||||
}
|
||||
|
||||
pub fn description(&self) -> &str {
|
||||
&self.description
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue