vncrs 0.1.3

A pure Rust VNC server library for Windows
Documentation
use crate::error::{Result, VncError};
use crate::protocol::auth;
use crate::protocol::pixel_format::PixelFormat;
use std::io::{Read, Write};

pub fn perform_handshake<R: Read, W: Write>(
    reader: &mut R,
    writer: &mut W,
    width: u16,
    height: u16,
    name: &str,
    pixel_format: &PixelFormat,
    password: Option<&str>,
) -> Result<()> {
    writer.write_all(b"RFB 003.008\n")?;
    writer.flush()?;

    let mut version = [0u8; 12];
    reader.read_exact(&mut version)?;
    let version_str = String::from_utf8_lossy(&version);
    println!("📡 Client version: {}", version_str.trim());

    if let Some(pass) = password {
        writer.write_all(&[1u8, 2u8])?;
        writer.flush()?;

        let mut chosen = [0u8; 1];
        reader.read_exact(&mut chosen)?;

        if chosen[0] != 2 {
            return Err(VncError::Handshake(format!(
                "Client chose unsupported security type: {}",
                chosen[0]
            )));
        }

        auth::perform_vnc_auth(reader, writer, pass)?;
    } else {
        writer.write_all(&[1u8, 1u8])?;
        writer.flush()?;

        let mut chosen = [0u8; 1];
        reader.read_exact(&mut chosen)?;

        writer.write_all(&0u32.to_be_bytes())?;
        writer.flush()?;
    }

    let mut shared_flag = [0u8; 1];
    reader.read_exact(&mut shared_flag)?;

    let mut init: Vec<u8> = Vec::new();
    init.extend_from_slice(&width.to_be_bytes());
    init.extend_from_slice(&height.to_be_bytes());
    init.extend_from_slice(&pixel_format.to_bytes());

    let name_bytes = name.as_bytes();
    init.extend_from_slice(&(name_bytes.len() as u32).to_be_bytes());
    init.extend_from_slice(name_bytes);

    writer.write_all(&init)?;
    writer.flush()?;

    Ok(())
}