I'm calling split
on a tokio::net::TcpStream
connection. The problem is that I don't know how to store the stream
and sink
, because both hold a reference to the TcpStream
:
use futures::prelude::*;
pub type MessageStream = Pin<Box<dyn Stream<Item = Result<rtsp_types::Message<Body>, ReadError>> + Send>>
pub type MessageSink = Pin<Box<dyn Sink<rtsp_types::Message<Body>, Error = std::io::Error> + Send>>
pub async fn connect(
&mut self,
addr: std::net::SocketAddr,
) -> std::result::Result<(), ClientError> {
let connection = tokio::net::TcpStream::connect(addr).await;
match connection {
Ok(mut connection) => {
let (read, write) = connection.split();
let stream = super::message_socket::async_read(read, super::MAX_MESSAGE_SIZE);
let sink = super::message_socket::async_write(write);
let stream: MessageStream = Box::pin(stream);
let sink: MessageSink = Box::pin(sink);
self.stream = Some(stream);
self.sink = Some(sink);
Ok(())
}
Err(err) => Err(ClientError::SocketAcceptError(err)),
}
}
pub(crate) fn async_write<W: tokio::io::AsyncWrite + Unpin + Send>(
write: W,
) -> impl Sink<Message<Body>, Error = std::io::Error> + Send;
pub(crate) fn async_read<R: tokio::io::AsyncRead + Unpin + Send>(
read: R,
max_size: usize,
) -> impl Stream<Item = Result<Message<Body>, ReadError>> + Send;
I solved this by doing
let (read, write) = connection.into_split();
which, instead of split
:
pub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)
allocates the ReadHalf and WriteHalf on the heap:
pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)
However, what if there were no into_split
method? How would I solve this?
I think that by specifying that the TcpStream
lifetime is 'static
, it'd solve, but what if I want to create lots of TcpStream
connections? They would all accumulate on RAM?
I'd have my struct something like this:
pub struct Client {
stream: Option<MessageStream<'a>>,
sink: Option<MessageSink<'a>>,
but I don't have idea about the lifetime of the TcpStream
.