use crate::handshake::errors::ClientHandshakeError; use crate::handshake::request::HandshakeRequest; use crate::handshake::response::HandshakeResponse; use crate::message::backend::{AuthenticationOkData, BackendMessage}; use crate::message::special::StartupMessageData; use crate::reader::backend::BackendProtoReader; use crate::writer::frontend::FrontendProtoWriter; use crate::writer::protowriter::ProtoFlush; /// Performs client-side handshake with the server until the `ReadyForQuery` message is received. /// For more info visit the [`55.2.1. Start-up`](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-START-UP) pub async fn do_client_handshake( writer: &mut (impl FrontendProtoWriter + ProtoFlush), reader: &mut impl BackendProtoReader, request: HandshakeRequest, ) -> Result { // Send StartupMessage without SSLRequest let startup_message: StartupMessageData = request.into(); writer.write_startup_message(startup_message).await?; writer.flush().await?; // Wait for AuthenticationOk let auth = reader.read_proto().await?; if !matches!( auth, BackendMessage::AuthenticationOk(AuthenticationOkData { status: 0 }) ) { return Err(ClientHandshakeError::UnexpectedAuthResponse(auth)); } // Read server parameter messages until ReadyForQuery is received let mut messages = Vec::new(); loop { let msg = reader.read_proto().await?; if matches!(msg, BackendMessage::ReadyForQuery(_)) { break; } messages.push(msg); } HandshakeResponse::try_from(messages.as_slice()) }