ciph 0.1.0

Symmetric cipher layer for async read/write connections.
Documentation
//! Integration tests using `hyper` HTTP Client and the `warp` webserver (built on `hyper`).
/*
use std::{
    thread,
    str::FromStr,
    convert::Infallible,
    net::SocketAddr,
    sync::mpsc,
};

use warp::Filter;
use bytes::Bytes;
use tokio::net::TcpListener;
use hyper::body::HttpBody;

use scl::salsa::{SalsaKey, Acceptor, StreamAcceptor, HttpSalsaConnector, Connector};

const KEY_B64: &str = include_str!("test.key");

fn api() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path("api")
        .and(warp::post())
        .and(warp::body::content_length_limit(137438953472))
        .and(warp::body::bytes())
        .and_then(echo)
}

// Just reply with what was received.
async fn echo(raw: Bytes) -> Result<impl warp::Reply, Infallible> {
    let body = warp::hyper::Body::from(raw);    
    Ok(warp::reply::Response::new(body))
}

fn spawn_localhost_server(key: SalsaKey) -> SocketAddr {
    let (addr_send, addr_recv) = mpsc::channel();

    thread::spawn(move || {
        let mut rt = tokio::runtime::Builder::new()
            .max_threads(1)
            .threaded_scheduler()
            .enable_io()
            .build()
            .unwrap();

        let handle = rt.handle().clone();
        
        let bound = rt.block_on(async move {
            let addr = SocketAddr::from(([127, 0, 0, 1], 0));
            let listener = TcpListener::bind(&addr)
                .await
                .expect("Cannot bind listen address.");

            let listen_addr = listener
                .local_addr()
                .unwrap();

            addr_send.send(listen_addr).unwrap();

            listener
        });

        let server_fut = handle.enter(move || {
            
            let acceptor = Acceptor::new(key);
            let incoming = StreamAcceptor::new(acceptor, bound);

            let server = warp::serve(api());

            server.serve_incoming(incoming)
        });

        rt.block_on(server_fut);
    });

    addr_recv
        .recv()
        .unwrap()    
}

#[tokio::test(core_threads = 1)]
async fn warp_salsa_cipher_works() -> Result<(), Box<dyn std::error::Error>> {
    const FILE: &'static [u8] = include_bytes!("../README.md");
    //let mut buffer: [u8; FILE.len()] = [0; FILE.len()];
    let key = SalsaKey::from_str(KEY_B64)?;
    let addr = spawn_localhost_server(key.clone());
    let connector = Connector::new(key);

    let uri_str = format!("http://localhost:{}/api", addr.port());
    let uri: hyper::Uri = uri_str.parse()?;
    let body = hyper::Body::from(FILE);
    let req = hyper::Request::builder()
        .uri(uri)
        .method("POST")
        .body(body)?;

    let salsa_connector = HttpSalsaConnector::new_http(connector);

    let client = hyper::client::Builder::default()
        .build::<_, hyper::Body>(salsa_connector);

    let mut response = client
        .request(req)
        .await?;

    let mut buffer: Vec<u8> = Vec::new();

    while let Some(chunk) = response.data().await {
        buffer.extend(chunk?);
    }

    assert_eq!(buffer.as_slice(), FILE);

    Ok(())
}
*/