// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! FIPS compliant random number conditioner. Reads from /dev/hw_random
//! and applies the NIST SP 800-90A CTR DRBG strategy to provide
//! pseudorandom bytes to clients which connect to a socket provided
//! by init.

mod conditioner;
mod cutils_socket;
mod drbg;

use std::{
    convert::Infallible,
    fs::remove_file,
    io::ErrorKind,
    os::unix::net::UnixListener,
    path::{Path, PathBuf},
};

use anyhow::{ensure, Context, Result};
use log::{error, info, Level};
use nix::sys::signal;
use tokio::{io::AsyncWriteExt, net::UnixListener as TokioUnixListener};

use crate::conditioner::ConditionerBuilder;

//#[derive(Debug, clap::Parser)]
struct Cli {
    //#[clap(long, default_value = "/dev/hw_random")]
    source: PathBuf,
    //#[clap(long)]
    socket: Option<PathBuf>,
}

fn configure_logging() -> Result<()> {
    ensure!(
        logger::init(
            logger::Config::default().with_tag_on_device("prng_seeder").with_min_level(Level::Info)
        ),
        "log configuration failed"
    );
    Ok(())
}

fn get_socket(path: &Path) -> Result<UnixListener> {
    if let Err(e) = remove_file(path) {
        if e.kind() != ErrorKind::NotFound {
            return Err(e).context(format!("Removing old socket: {}", path.display()));
        }
    } else {
        info!("Deleted old {}", path.display());
    }
    UnixListener::bind(path)
        .with_context(|| format!("In get_socket: binding socket to {}", path.display()))
}

fn setup() -> Result<(ConditionerBuilder, UnixListener)> {
    configure_logging()?;
    let cli = Cli { source: PathBuf::from("/dev/hw_random"), socket: None };
    unsafe { signal::signal(signal::Signal::SIGPIPE, signal::SigHandler::SigIgn) }
        .context("In setup, setting SIGPIPE to SIG_IGN")?;

    let listener = match cli.socket {
        Some(path) => get_socket(path.as_path())?,
        None => cutils_socket::android_get_control_socket("prng_seeder")
            .context("In setup, calling android_get_control_socket")?,
    };
    let hwrng = std::fs::File::open(&cli.source)
        .with_context(|| format!("Unable to open hwrng {}", cli.source.display()))?;
    let cb = ConditionerBuilder::new(hwrng)?;
    Ok((cb, listener))
}

async fn listen_loop(cb: ConditionerBuilder, listener: UnixListener) -> Result<Infallible> {
    let mut conditioner = cb.build();
    listener.set_nonblocking(true).context("In listen_loop, on set_nonblocking")?;
    let listener = TokioUnixListener::from_std(listener).context("In listen_loop, on from_std")?;
    info!("Starting listen loop");
    loop {
        match listener.accept().await {
            Ok((mut stream, _)) => {
                let new_bytes = conditioner.request()?;
                tokio::spawn(async move {
                    if let Err(e) = stream.write_all(&new_bytes).await {
                        error!("Request failed: {}", e);
                    }
                });
                conditioner.reseed_if_necessary().await?;
            }
            Err(e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e).context("accept on socket failed"),
        }
    }
}

fn run() -> Result<Infallible> {
    let (cb, listener) = match setup() {
        Ok(t) => t,
        Err(e) => {
            // If setup fails, just hang forever. That way init doesn't respawn us.
            error!("Hanging forever because setup failed: {:?}", e);
            // Logs are sometimes mysteriously not being logged, so print too
            println!("prng_seeder: Hanging forever because setup failed: {:?}", e);
            loop {
                std::thread::park();
                error!("std::thread::park() finished unexpectedly, re-parking thread");
            }
        }
    };

    tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .context("In run, building reactor")?
        .block_on(async { listen_loop(cb, listener).await })
}

fn main() {
    let e = run();
    error!("Launch terminated: {:?}", e);
    // Logs are sometimes mysteriously not being logged, so print too
    println!("prng_seeder: launch terminated: {:?}", e);
    std::process::exit(-1);
}
