loco-protocol 0.1.0

Loco protocol implementation
Documentation

loco-protocol - Loco protocol implementation

Open source Loco protocol implemention made with rust

Specification

Command

name size
header (Header) 22 bytes
data header.data_size

Header

name size
id 4 bytes
status 2 bytes
name 11 bytes
data_type 1 bytes
data_size 4 bytes

Secure data

name size
header (Header) 20 bytes
encrypted data header.size - 16

Header

name size
iv 16 bytes
size 4 bytes

Handshake

name size
key size 4 bytes
key_encrypt_type 4 bytes
encrypt_type 4 bytes
key 256 bytes

Note: current implemention only supports RSA-AES

Example

use std::{net::{TcpListener, TcpStream}, thread, io};
use openssl::rsa::Rsa;
use loco_protocol::{command::{Command, Error, Header, processor::CommandProcessor}, io::SecureClientStream, io::SecureServerStream, secure::CryptoStore};
    
fn main() {
    let key = Rsa::generate(2048).expect("Cannot generate rsa key pairs.");
    
    let socket = TcpListener::bind("127.0.0.1:5022").expect("Cannot bind tcp server");
    socket.set_nonblocking(true).expect("Cannot set socket to unblocked mode");
    
    let tcp = TcpStream::connect("127.0.0.1:5022").expect("Cannot connect tcp stream");
    tcp.set_nonblocking(true).expect("Cannot set client stream to unblocked mode");
    
    let mut client = CommandProcessor::new(
        SecureClientStream::new(
            CryptoStore::new().unwrap(),
            key.clone(),
            tcp
        )
    );
    
    let command = Command {
        header: Header {
            id: 0,
            status: 0,
            name: [72_u8, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0],
            data_type: 0,
            data_size: 5
        },
        
        data: "Hello".as_bytes().into(),
    };
    
    client.write_commmand(command.clone()).expect("Failed to send command");
    println!("CLIENT -> {:?}", command.clone());
    
    loop {
        match socket.accept() {
    
            Ok(connection) => {
                let key = key.clone();

                thread::spawn(move || {
                    let mut server = CommandProcessor::new(
                        SecureServerStream::new(
                            CryptoStore::new().unwrap(),
                            key,
                            connection.0
                        )
                    );
    
                    println!("Connected from {}", connection.1);
                    loop {
                        match server.read_commmand() {
    
                            Ok(readed) => {
                                if readed.is_some() {
                                    let received = readed.unwrap();
                                    println!("SERVER <- {:?}", received.clone());
    
                                    server.write_commmand(received.clone()).expect("Command failed to write");
                                    println!("SERVER -> {:?}", received.clone());
                                    break;
                                }
                            }
    
                            Err(err) => panic!(format!("{}", err))
                        }
                    }
                });
            }
    
            Err(err) if err.kind() == io::ErrorKind::WouldBlock => {  }
    
            Err(err) => panic!(format!("{}", err))
        }
    
        match client.read_commmand() {
    
            Ok(readed) => {
                match readed {
    
                    Some(received) => {
                        println!("CLIENT <- {:?}", received);
                        return;
                    }
    
                    None => {}
                }
            }
    
            Err(err) => {
                match err {
                    Error::Io(io_err) if io_err.kind() == io::ErrorKind::WouldBlock => {}
                    
                    _ => panic!(format!("{}", err))
                }
            }
        }
    }
}

License

loco-protocol is following MIT License.