Help in using tokio_native_tls for async TLS communication

Hi

Currently my code has problems sending/receiving data from a ncat listener. I observed in Wireshark that the TCP/TLS handshakes worked fine, but when I tried to send data from the console to the ncat listener, the data does not get sent as I did not observe any network traffic.

If I used the ncat listener console to send data back, I can see the network traffic in Wireshark but my program does not print out the data.

Perhaps I shouldn't use Arc/Mutex in this case?

async fn read_pipe(tls_clone: std::sync::Arc<std::sync::Mutex<tokio_native_tls::TlsStream<tokio::net::TcpStream>>>) -> std::io::Result<()>
{
	let mut thread_unwrapped = tls_clone.lock().unwrap();
	let mut tokio_stdout = tokio::io::stdout();
	let mut tokio_stdin = tokio::io::stdin();

	loop
    {
    	let mut buffer2 = [0; 256];
		thread_unwrapped.read(&mut buffer2).await?;
		tokio_stdout.write(&buffer2).await?;
    }

    Ok(())
}

async fn write_pipe(tls_clone2: std::sync::Arc<std::sync::Mutex<tokio_native_tls::TlsStream<tokio::net::TcpStream>>>) -> std::io::Result<()>
{
	let mut thread_unwrapped = tls_clone2.lock().unwrap();
	let mut tokio_stdout = tokio::io::stdout();
	let mut tokio_stdin = tokio::io::stdin();

	loop
    {
		let mut message2 = [0; 256];

		tokio_stdin.read(&mut message2).await?;

		thread_unwrapped.write(&message2).await?;
    }

    Ok(())
}

async fn initiate_tls() -> std::io::Result<()>
{
	let tcp_stream = tokio::net::TcpStream::connect("127.0.0.1:4444").await;

	match tcp_stream
	{
		Ok(working_stream) =>
		{
			let mut native_tls_builder = native_tls::TlsConnector::builder();
			native_tls_builder.danger_accept_invalid_certs(true);
			native_tls_builder.danger_accept_invalid_hostnames(true);
			native_tls_builder.use_sni(false);

			let native_tls_connector = native_tls_builder.build().unwrap();

			let tokio_tls_connector = tokio_native_tls::TlsConnector::from(native_tls_connector);
			let mut working_stream = tokio_tls_connector.connect("127.0.0.1:4444",working_stream).await;

			match working_stream
			{
				Ok(mut working_tls) =>
				{
					let arc_tls = Arc::new(Mutex::new(working_tls));

					let tls_clone = Arc::clone(&arc_tls);
					let tls_clone2 = Arc::clone(&arc_tls);

					let read_future = read_pipe(tls_clone);
					let write_future = write_pipe(tls_clone2);

					futures::join!(read_future,write_future);
				}

				Err(error) =>
				{
					panic!("Error establishing TLS connection {}",error);
				}
			}

		}

		Err(error) =>
		{
			panic!("cannot establish TCP stream {}",error);
		}
	}

	Ok(())
}

#[tokio::main]
async fn main()
{
    initiate_tls().await;
}

I very very strongly recommend removing those arcs and mutexes. Consider reading this. Your code only compiles because you didn't spawn it, but ran it directly in main which has no Send requirement.

I haven't looked closely, but it's likely that you broke it by causing a deadlock using that mutex.

Yeah, it's definitely a deadlock on the mutex. Use tokio::io::split instead of an arc/mutex.

Thanks @alice, I will take a look at those links.

Hi @alice

I looked into tokio::io::split but I ran into more issues. If I tried to read from/write to the read/write halves of the TcpStream directly, it will cause problems as I am running TLS on top of the TCP Stream.

I am not able to receive/send data to the ncat listener.

Are you splitting the TCP stream, or the TLS stream? You're supposed to split the TLS stream.

Hi @alice

Thanks, it works now.