rust_voice_chat_room/client/src/stream.rs

132 lines
4.5 KiB
Rust
Raw Normal View History

use std::{net::SocketAddr, path::Path, sync::Arc};
2025-05-20 05:44:00 +03:00
use protocol::Error;
use s2n_quic::{
Client,
client::Connect,
stream::{ReceiveStream, SendStream},
};
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
sync::{broadcast, oneshot},
};
2025-05-20 05:44:00 +03:00
use crate::{ClientConfig, SPEAKER_BUFFER_LENGHT, voice::play};
pub async fn connect(
connection_stop_signal_receiver: oneshot::Receiver<bool>,
is_connection_started_signal: oneshot::Sender<bool>,
microphone_sender_for_producing_receiver: Arc<broadcast::Sender<f32>>,
client_config: Arc<ClientConfig>,
) -> Result<(), Error> {
let client = Client::builder()
.with_io("0:0")
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?
.with_tls(Path::new(&client_config.certificate_path))
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?
.start()
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?;
println!("Client Address = {}", client.local_addr().unwrap());
let connect = Connect::new(
client_config
.server_address
.parse::<SocketAddr>()
.map_err(|inner| Error::Connection(inner.to_string()))?,
)
.with_server_name("localhost");
let mut connection = match client.connect(connect).await {
Ok(connection) => connection,
Err(err_val) => {
eprintln!("Error: Client Connection | {}", err_val);
return Err(Error::Connection(err_val.to_string()));
}
};
connection
.keep_alive(true)
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?;
let stream = connection
.open_bidirectional_stream()
.await
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?;
let (receive_stream, send_stream) = stream.split();
2025-05-20 05:44:00 +03:00
let (speaker_sender, speaker_receiver) = broadcast::channel(SPEAKER_BUFFER_LENGHT);
let (speaker_stop_signal_sender, speaker_stop_signal_receiver) = oneshot::channel();
tokio::spawn(play(speaker_receiver, speaker_stop_signal_receiver));
2025-05-20 00:59:34 +03:00
let receive_voice_data_task = tokio::spawn(receive_audio_data(receive_stream, speaker_sender));
let send_voice_data_task = tokio::spawn(send_audio_data(
send_stream,
microphone_sender_for_producing_receiver,
));
if let Err(err_val) = is_connection_started_signal.send(true) {
2025-05-20 00:59:34 +03:00
eprintln!("Error: Is Connection Started | Local | Send | {}", err_val);
}
if let Err(err_val) = connection_stop_signal_receiver.await {
eprintln!(
2025-05-20 00:59:34 +03:00
"Error: Connection Stop Signal | Local | Receive | {}",
err_val
);
}
if let Err(err_val) = speaker_stop_signal_sender.send(true) {
2025-05-20 00:59:34 +03:00
eprintln!("Error: Speaker Stop Signal | Local | Send | {}", err_val);
}
println!("Connection Is Closing");
receive_voice_data_task.abort();
send_voice_data_task.abort();
println!("Connection Is Closed");
Ok(())
}
2025-05-20 00:59:34 +03:00
async fn send_audio_data(
mut send_stream: SendStream,
microphone_sender_for_producing_receiver: Arc<broadcast::Sender<f32>>,
) {
let mut microphone_receiver = microphone_sender_for_producing_receiver.subscribe();
loop {
match microphone_receiver.recv().await {
Ok(microphone_data) => {
if let Err(err_val) = send_stream.write_f32(microphone_data).await {
2025-05-20 00:59:34 +03:00
eprintln!("Error: Send Microphone Data | Remote | {}", err_val);
break;
}
}
Err(err_val) => {
2025-05-20 00:59:34 +03:00
eprintln!("Error: Receive from Microphone | Local | {}", err_val);
match err_val {
broadcast::error::RecvError::Closed => break,
broadcast::error::RecvError::Lagged(_) => {
microphone_receiver = microphone_receiver.resubscribe()
}
}
}
}
}
}
2025-05-20 00:59:34 +03:00
async fn receive_audio_data(
mut receive_stream: ReceiveStream,
speaker_sender: broadcast::Sender<f32>,
) {
loop {
match receive_stream.read_f32().await {
Ok(received_data) => {
if let Err(err_val) = speaker_sender.send(received_data) {
2025-05-20 00:59:34 +03:00
eprintln!("Error: Send to Speaker | Local | {}", err_val);
break;
}
}
Err(err_val) => {
2025-05-20 00:59:34 +03:00
eprintln!("Error: Receive Audio Data | Remote | {}", err_val);
break;
}
}
}
}