moblink-rust 0.9.4

Use spare devices as extra SRTLA bonding connections
Documentation
use base64::Engine as _;
use base64::engine::general_purpose;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use uuid::Uuid;

pub const API_VERSION: &str = "1.0";

#[derive(Deserialize, Serialize, Debug)]
pub struct Present {}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum MoblinkResult {
    Ok(Present),
    WrongPassword(Present),
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Authentication {
    pub challenge: String,
    pub salt: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Hello {
    #[serde(rename = "apiVersion")]
    #[allow(dead_code)]
    pub api_version: String,
    pub authentication: Authentication,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Identified {
    pub result: MoblinkResult,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct StartTunnelRequest {
    pub address: String,
    pub port: u16,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum MessageRequestData {
    StartTunnel(StartTunnelRequest),
    Status(Present),
}

#[derive(Serialize, Deserialize, Debug)]
pub struct MessageRequest {
    pub id: u32,
    pub data: MessageRequestData,
}

impl MessageRequest {
    pub fn to_ok_response(&self, data: ResponseData) -> MessageResponse {
        MessageResponse {
            id: self.id,
            result: MoblinkResult::Ok(Present {}),
            data,
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct StartTunnelResponseData {
    pub port: u16,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct StatusResponseData {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub battery_percentage: Option<i32>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum ResponseData {
    StartTunnel(StartTunnelResponseData),
    Status(StatusResponseData),
}

#[derive(Serialize, Deserialize, Debug)]
pub struct MessageResponse {
    pub id: u32,
    pub result: MoblinkResult,
    pub data: ResponseData,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Identify {
    pub id: Uuid,
    pub name: String,
    pub authentication: String,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum MessageToRelay {
    Hello(Hello),
    Identified(Identified),
    Request(MessageRequest),
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum MessageToStreamer {
    Identify(Identify),
    Response(MessageResponse),
}

pub fn calculate_authentication(password: &str, salt: &str, challenge: &str) -> String {
    let mut hasher = Sha256::new();
    hasher.update(format!("{}{}", password, salt).as_bytes());
    let hash1 = hasher.finalize_reset();
    hasher.update(format!("{}{}", general_purpose::STANDARD.encode(hash1), challenge).as_bytes());
    let hash2 = hasher.finalize();
    general_purpose::STANDARD.encode(hash2)
}