realm_core 0.5.1

Realm's core facilities.
Documentation
use std::io::Result;
use futures::try_join;

use kaminari::{AsyncAccept, AsyncConnect, IOStream};
use kaminari::mix::{MixAccept, MixConnect};

use realm_io::{CopyBuffer, bidi_copy_buf, buf_size};

pub async fn run_relay<S: IOStream>(src: S, dst: S, ac: &MixAccept, cc: &MixConnect) -> Result<()> {
    macro_rules! hs_relay {
        ($ac: expr, $cc: expr) => {
            handshake_and_relay(src, dst, $ac, $cc).await
        };
    }

    #[cfg(feature = "transport-boost")]
    {
        use MixConnect::*;
        if let Some(ac) = ac.as_plain() {
            return match cc {
                Plain(cc) => hs_relay!(ac, cc),
                Ws(cc) => hs_relay!(ac, cc),
                Tls(cc) => hs_relay!(ac, cc),
                Wss(cc) => hs_relay!(ac, cc),
            };
        }
    }

    #[cfg(feature = "transport-boost")]
    {
        use MixAccept::*;
        if let Some(cc) = cc.as_plain() {
            return match ac {
                Plain(ac) => hs_relay!(ac, cc),
                Ws(ac) => hs_relay!(ac, cc),
                Tls(ac) => hs_relay!(ac, cc),
                Wss(ac) => hs_relay!(ac, cc),
            };
        }
    }

    hs_relay!(ac, cc)
}

async fn handshake_and_relay<S, AC, CC>(src: S, dst: S, ac: &AC, cc: &CC) -> Result<()>
where
    S: IOStream,
    AC: AsyncAccept<S>,
    CC: AsyncConnect<S>,
{
    let mut buf1 = vec![0; buf_size()];
    let mut buf2 = vec![0; buf_size()];

    let (mut src, mut dst) = try_join!(ac.accept(src, &mut buf1), cc.connect(dst, &mut buf2))?;

    let buf1 = CopyBuffer::new(buf1);
    let buf2 = CopyBuffer::new(buf2);

    bidi_copy_buf(&mut src, &mut dst, buf1, buf2).await.map(|_| ())
}