whatsapp_rust/
handshake.rs1use crate::socket::{FrameSocket, NoiseSocket};
2use log::{debug, info};
3use std::sync::Arc;
4use thiserror::Error;
5use tokio::time::{Duration, timeout};
6use wacore::handshake::{HandshakeState, utils::HandshakeError as CoreHandshakeError};
7
8const NOISE_HANDSHAKE_RESPONSE_TIMEOUT: Duration = Duration::from_secs(20);
9
10#[derive(Debug, Error)]
11pub enum HandshakeError {
12 #[error("WebSocket error: {0}")]
13 Socket(#[from] crate::socket::error::SocketError),
14 #[error("Core handshake error: {0}")]
15 Core(#[from] CoreHandshakeError),
16 #[error("Timed out waiting for handshake response")]
17 Timeout,
18}
19
20type Result<T> = std::result::Result<T, HandshakeError>;
21
22pub async fn do_handshake(
23 device: &crate::store::Device,
24 frame_socket: &mut FrameSocket,
25 frames_rx: &mut tokio::sync::mpsc::Receiver<bytes::Bytes>,
26) -> Result<Arc<NoiseSocket>> {
27 let mut handshake_state = HandshakeState::new(&device.core)?;
28
29 debug!("--> Sending ClientHello");
30 let client_hello_bytes = handshake_state.build_client_hello()?;
31 frame_socket.send_frame(client_hello_bytes).await?;
32
33 let resp_frame = timeout(NOISE_HANDSHAKE_RESPONSE_TIMEOUT, frames_rx.recv())
34 .await
35 .map_err(|_| HandshakeError::Timeout)?
36 .ok_or(HandshakeError::Timeout)?;
37
38 debug!("<-- Received handshake response, building ClientFinish");
39 let client_finish_bytes =
40 handshake_state.read_server_hello_and_build_client_finish(&resp_frame)?;
41
42 debug!("--> Sending ClientFinish");
43 frame_socket.send_frame(client_finish_bytes).await?;
44
45 let (write_key, read_key) = handshake_state.finish()?;
46 info!(target: "Client", "Handshake complete, switching to encrypted communication");
47
48 let frame_socket_arc = std::sync::Arc::new(tokio::sync::Mutex::new(std::mem::replace(
49 frame_socket,
50 FrameSocket::new().0,
51 )));
52
53 Ok(Arc::new(NoiseSocket::new(
54 frame_socket_arc,
55 write_key,
56 read_key,
57 )))
58}