tentacli 15.2.1

Framework for building extensible network protocol clients via modular plugins.
use async_trait::async_trait;
use binrw::BinRead;
use serde::Serialize;
use std::mem;
use std::sync::{Arc, Mutex};
use tokio::sync::RwLock;

use crate::client::prelude::*;
use crate::plugins::wow::wotlk::login;
use crate::plugins::wow::wotlk::login::srp::Srp;

#[derive(Packet, BinRead, Serialize, FieldsMetadata)]
#[br(little)]
pub struct Incoming {
    error: u8,
    server_proof: [u8; 20],
    account_flags: u32,
    survey_id: u32,
    unknown_flags: u16,
}

pub struct Handler {
    pub srp: Arc<Mutex<Srp>>,
}

#[async_trait]
impl PacketHandler for Handler {
    async fn handle(
        &mut self,
        packet: &mut Packet,
        _: Arc<RwLock<CtxMap>>,
    ) -> anyhow::Result<Vec<HandlerOutput>> {
        let mut outputs = vec![];
        let Incoming { server_proof, .. } = Incoming::unpack(packet)?;

        let is_valid_proof = self
            .srp
            .lock()
            .map_err(|_| anyhow::anyhow!("Mutex poisoned"))?
            .validate_proof(server_proof);

        if !is_valid_proof {
            outputs.extend([
                HandlerOutput::Messages(vec![Message {
                    msg_type: MsgType::Error,
                    text: "Proof is not valid".to_string(),
                }]),
                HandlerOutput::Requests(vec![Request::Drop(login::PLUGIN_LABEL)]),
            ]);
        } else {
            let session_key = {
                let mut guard = self
                    .srp
                    .lock()
                    .map_err(|_| anyhow::anyhow!("Mutex poisoned"))?;
                mem::take(&mut guard.session_key)
            };

            outputs.extend([
                HandlerOutput::Messages(vec![Message {
                    msg_type: MsgType::Success,
                    text: "Proof is valid".to_string(),
                }]),
                HandlerOutput::Requests(vec![Request::SetContext(Some(Box::new(
                    move |ctx: &mut CtxMap| {
                        ctx.insert(Secret(session_key));
                    },
                )))]),
            ]);
        }

        Ok(outputs)
    }
}

pub struct Secret(pub Vec<u8>);