tunneler 0.4.0

Tunnel TCP or UDP traffic over TCP, (mutual) TLS or DNS (authoritative server or direct connection)
Documentation
use std::error::Error;

use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use std::convert::TryInto;

pub trait Encoder: Send {
    fn calculate_max_decoded_size(&self, max_encoded_size: usize) -> usize;
    fn encode(&self, data: &[u8]) -> Result<String, Box<dyn Error>>;
}

pub trait Decoder: Send {
    fn decode(&self, data: &str) -> Result<Vec<u8>, Box<dyn Error>>;
}

pub struct HexEncoder {}

impl Encoder for HexEncoder {
    fn calculate_max_decoded_size(&self, max_encoded_size: usize) -> usize {
        max_encoded_size / 2
    }
    fn encode(&self, data: &[u8]) -> Result<String, Box<dyn Error>> {
        Ok(hex::encode(data))
    }
}

pub struct HexDecoder {}

impl Decoder for HexDecoder {
    fn decode(&self, data: &str) -> Result<Vec<u8>, Box<dyn Error>> {
        match hex::decode(data) {
            Ok(v) => Ok(v),
            Err(e) => Err(e.into()),
        }
    }
}

pub const CLIENT_ID_SIZE_IN_BYTES: usize = 4;
pub type ClientId = [u8; CLIENT_ID_SIZE_IN_BYTES];

pub fn new_client_id() -> ClientId {
    let values: Vec<u8> = thread_rng()
        .sample_iter(&Alphanumeric)
        .take(CLIENT_ID_SIZE_IN_BYTES)
        .collect();
    values.try_into().unwrap()
}

pub struct ClientIdSuffixEncoder<E: Encoder> {
    encoder: E,
}

impl<E: Encoder> ClientIdSuffixEncoder<E> {
    pub fn new(encoder: E) -> Self {
        Self { encoder }
    }
}

impl<E: Encoder> Encoder for ClientIdSuffixEncoder<E> {
    fn calculate_max_decoded_size(&self, max_encoded_size: usize) -> usize {
        self.encoder.calculate_max_decoded_size(max_encoded_size) - CLIENT_ID_SIZE_IN_BYTES
    }

    fn encode(&self, data: &[u8]) -> Result<String, Box<dyn Error>> {
        if data.len() < CLIENT_ID_SIZE_IN_BYTES {
            return Err(String::from("not enough data to encode").into());
        }

        let (data, client_id) = data.split_at(data.len() - CLIENT_ID_SIZE_IN_BYTES);
        let mut res = self.encoder.encode(data)?;
        let encoded_client_id = std::str::from_utf8(client_id).unwrap();
        res.push_str(encoded_client_id);
        Ok(res)
    }
}

pub struct ClientIdSuffixDecoder<D: Decoder> {
    decoder: D,
}

impl<D: Decoder> ClientIdSuffixDecoder<D> {
    pub fn new(decoder: D) -> Self {
        Self { decoder }
    }
}

impl<D: Decoder> Decoder for ClientIdSuffixDecoder<D> {
    fn decode(&self, data: &str) -> Result<Vec<u8>, Box<dyn Error>> {
        if data.len() < CLIENT_ID_SIZE_IN_BYTES {
            return Err(String::from("not enough data to decode").into());
        }

        let (data, client_id) = data.split_at(data.len() - CLIENT_ID_SIZE_IN_BYTES);
        let mut res = self.decoder.decode(data)?;
        let decoded_client_id = client_id.as_bytes();
        res.extend_from_slice(decoded_client_id);
        Ok(res)
    }
}

pub struct AppendSuffixEncoder<E: Encoder> {
    encoder: E,
    suffix: String,
}

impl<E: Encoder> AppendSuffixEncoder<E> {
    pub fn new(encoder: E, suffix: String) -> Self {
        Self { encoder, suffix }
    }
}

impl<E: Encoder> Encoder for AppendSuffixEncoder<E> {
    fn calculate_max_decoded_size(&self, max_encoded_size: usize) -> usize {
        self.encoder.calculate_max_decoded_size(max_encoded_size) - self.suffix.len()
    }

    fn encode(&self, data: &[u8]) -> Result<String, Box<dyn Error>> {
        let mut res = self.encoder.encode(data)?;
        res.push_str(self.suffix.as_str());
        Ok(res)
    }
}

pub struct AppendSuffixDecoder<D: Decoder> {
    decoder: D,
    suffix: String,
}

impl<D: Decoder> AppendSuffixDecoder<D> {
    pub fn new(decoder: D, suffix: String) -> Self {
        Self { decoder, suffix }
    }
}

impl<D: Decoder> Decoder for AppendSuffixDecoder<D> {
    fn decode(&self, data: &str) -> Result<Vec<u8>, Box<dyn Error>> {
        let data_without_suffix = data
            .strip_suffix(self.suffix.as_str())
            .ok_or_else(|| String::from("missing suffix"))?;
        self.decoder.decode(data_without_suffix)
    }
}

#[cfg(test)]
mod tests {

    use mockall::mock;

    use super::*;

    mock! {
        Encoder{}
        impl Encoder for Encoder {
            fn calculate_max_decoded_size(&self, max_encoded_size: usize) -> usize;
            fn encode(&self, data: &[u8]) -> Result<String, Box<dyn Error>>;
        }
    }

    mock! {
        Decoder{}
        impl Decoder for Decoder {
            fn decode(&self, data: &str) -> Result<Vec<u8>, Box<dyn Error>>;
        }
    }

    #[test]
    fn client_id_suffix_encoder_not_enough_data() -> Result<(), Box<dyn Error>> {
        let encoder_mock = MockEncoder::new();
        let encoder = ClientIdSuffixEncoder::new(encoder_mock);
        let res = encoder.encode(b"123");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn client_id_suffix_encoder_internal_encoder_failed() -> Result<(), Box<dyn Error>> {
        let mut encoder_mock = MockEncoder::new();
        encoder_mock
            .expect_encode()
            .returning(|_| Err(String::from("bla").into()));
        let encoder = ClientIdSuffixEncoder::new(encoder_mock);
        let res = encoder.encode(b"bla1234");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn client_id_suffix_encoder_success() -> Result<(), Box<dyn Error>> {
        let mut encoder_mock = MockEncoder::new();
        encoder_mock
            .expect_encode()
            .returning(|_| Ok(String::from("encoded")));
        let encoder = ClientIdSuffixEncoder::new(encoder_mock);
        let res = encoder.encode(b"bla1234")?;
        assert_eq!("encoded1234", res);
        Ok(())
    }

    #[test]
    fn client_id_suffix_decoder_not_enough_data() -> Result<(), Box<dyn Error>> {
        let decoder_mock = MockDecoder::new();
        let decoder = ClientIdSuffixDecoder::new(decoder_mock);
        let res = decoder.decode("123");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn client_id_suffix_decoder_internal_decoder_failed() -> Result<(), Box<dyn Error>> {
        let mut decoder_mock = MockDecoder::new();
        decoder_mock
            .expect_decode()
            .returning(|_| Err(String::from("bla").into()));
        let decoder = ClientIdSuffixDecoder::new(decoder_mock);
        let res = decoder.decode("bla1234");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn client_id_suffix_decoder_success() -> Result<(), Box<dyn Error>> {
        let mut decoder_mock = MockDecoder::new();
        decoder_mock
            .expect_decode()
            .returning(|_| Ok(String::from("decoded").into_bytes()));
        let decoder = ClientIdSuffixDecoder::new(decoder_mock);
        let res = decoder.decode("bla1234")?;
        assert_eq!(b"decoded1234", res.as_slice());
        Ok(())
    }

    #[test]
    fn append_suffix_encoder_internal_encoder_failed() -> Result<(), Box<dyn Error>> {
        let suffix = String::from("xyz");
        let mut encoder_mock = MockEncoder::new();
        encoder_mock
            .expect_encode()
            .returning(|_| Err(String::from("bla").into()));
        let encoder = AppendSuffixEncoder::new(encoder_mock, suffix);
        let res = encoder.encode(b"bla");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn append_suffix_encoder_success() -> Result<(), Box<dyn Error>> {
        let suffix = String::from("xyz");
        let mut encoder_mock = MockEncoder::new();
        encoder_mock
            .expect_encode()
            .returning(|_| Ok(String::from("encoded")));
        let encoder = AppendSuffixEncoder::new(encoder_mock, suffix);
        let res = encoder.encode(b"bla")?;
        assert_eq!("encodedxyz", res);
        Ok(())
    }

    #[test]
    fn append_suffix_decoder_missing_suffix() -> Result<(), Box<dyn Error>> {
        let suffix = String::from("xyz");
        let decoder_mock = MockDecoder::new();
        let decoder = AppendSuffixDecoder::new(decoder_mock, suffix);
        let res = decoder.decode("123");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn append_suffix_decoder_internal_decoder_failed() -> Result<(), Box<dyn Error>> {
        let suffix = String::from("xyz");
        let mut decoder_mock = MockDecoder::new();
        decoder_mock
            .expect_decode()
            .returning(|_| Err(String::from("bla").into()));
        let decoder = AppendSuffixDecoder::new(decoder_mock, suffix);
        let res = decoder.decode("blaxyz");
        assert!(res.is_err());
        Ok(())
    }

    #[test]
    fn append_suffix_decoder_success() -> Result<(), Box<dyn Error>> {
        let suffix = String::from("xyz");
        let mut decoder_mock = MockDecoder::new();
        decoder_mock
            .expect_decode()
            .returning(|_| Ok(String::from("decoded").into_bytes()));
        let decoder = AppendSuffixDecoder::new(decoder_mock, suffix);
        let res = decoder.decode("blaxyz")?;
        assert_eq!(b"decoded", res.as_slice());
        Ok(())
    }
}