zero-trust-rps 0.0.3

Online Multiplayer Rock Paper Scissors
Documentation
use quinn::Connection;

use crate::common::connection::quic::QuicReader;
use crate::common::{
    connection::{Reader, Writer},
    message::{ClientMessage, ServerMessage, PROTOCOL_VERSION},
    result::DynResult,
};

#[allow(unused)]
pub async fn initialize_connection(
    connection: Connection,
    domain: &str,
    port: u16,
) -> DynResult<(Connection, impl Writer, impl Reader)> {
    initialize_connection_private(connection, domain, port, false).await
}

#[inline]
pub async fn finalize_connection(
    connection: Connection,
) -> DynResult<(Connection, impl Writer, impl Reader)> {
    let (writer, reader) = connection.accept_bi().await?;
    Ok((connection, writer, QuicReader::from(reader)))
}

#[inline]
pub(crate) async fn initialize_connection_private(
    connection: Connection,
    domain: &str,
    port: u16,
    print_to_stdout: bool,
) -> DynResult<(Connection, impl Writer, impl Reader)> {
    if print_to_stdout {
        println!("Connecting to {domain}:{port}");
    }
    log::info!("Connecting to {domain}:{port}");

    let (connection, mut writer, mut reader) = finalize_connection(connection).await?;

    let (server_version, hash) = match reader.get_next_message::<ServerMessage>().await? {
        Some(ServerMessage::Hello(vprot, vcrate, hash)) => {
            if vprot == PROTOCOL_VERSION {
                (vcrate, hash)
            } else {
                Err(format!(
                    "Server ({vcrate}) using unsupported protocol {vprot}"
                ))?
            }
        }
        Some(other) => Err(format!("Got unexpected first message: {other:?}"))?,
        None => Err("Got no message.")?,
    };

    let random_num = rand::random();
    writer
        .write_message(ClientMessage::Ping { c: random_num })
        .await?;

    match reader.get_next_message::<ServerMessage>().await? {
        Some(ServerMessage::Pong { c }) if c == random_num => {
            if let Some(hash) = hash {
                if print_to_stdout {
                    println!(
                        "Connected to Server at {:?} ({server_version}, {hash})",
                        connection.remote_address(),
                    );
                }
                log::info!(
                    "Connected to Server at {:?} ({server_version}, {hash})",
                    connection.remote_address()
                );
            } else {
                if print_to_stdout {
                    println!(
                        "Connected to Server at {:?} ({server_version})",
                        connection.remote_address(),
                    );
                }
                log::info!(
                    "Connected to Server at {:?} ({server_version})",
                    connection.remote_address()
                );
            }

            Ok((connection, writer, reader))
        }
        Some(other) => Err(format!("Got unexpected second message: {other:?}"))?,
        None => Err("Got no message.")?,
    }
}