pai-sho 0.3.0

What happens when you want dumbpipe to stay running, handle a few ports at once, and reconnect when your laptop wakes up
//! CLI client - sends commands to daemon over Unix socket.

use crate::protocol::{Request, Response};
use crate::Command;
use anyhow::{Context, Result};
use std::path::Path;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::UnixStream;

pub async fn send_command(socket_path: &Path, command: Command) -> Result<()> {
    let request = match command {
        Command::AddPeer { ticket } => Request::AddPeer { ticket },
        Command::RemovePeer { ticket } => Request::RemovePeer { ticket },
        Command::Expose { port, to } => Request::Expose { port, to },
        Command::Unexpose { port, to } => Request::Unexpose { port, to },
        Command::List => Request::List,
        Command::Ticket => Request::Ticket,
        Command::GrantToken { label } => Request::GrantToken { label },
        Command::Pin { key, label } => Request::Pin { key, label },
        Command::Daemon { .. } => unreachable!("daemon handled separately"),
    };

    let stream = UnixStream::connect(socket_path)
        .await
        .context("failed to connect to daemon - is it running?")?;

    let (reader, mut writer) = stream.into_split();
    let mut reader = BufReader::new(reader);

    // Send request
    let request_json = serde_json::to_string(&request)?;
    writer.write_all(request_json.as_bytes()).await?;
    writer.write_all(b"\n").await?;

    // Read response
    let mut line = String::new();
    reader.read_line(&mut line).await?;
    let response: Response = serde_json::from_str(&line)?;

    // Print response
    match response {
        Response::Ok => println!("OK"),
        Response::Ticket(ticket) => println!("{}", ticket),
        Response::Token(token) => println!("{}", token),
        Response::List(info) => {
            println!("{}", serde_json::to_string_pretty(&info)?);
        }
        Response::Error(e) => {
            eprintln!("Error: {}", e);
            std::process::exit(1);
        }
    }

    Ok(())
}