vake 1.0.0

Custom build tool for the In Silico project
Documentation
use std::{net::Ipv4Addr, sync::{Arc, Mutex}};
use tokio::{io::{AsyncBufReadExt, AsyncWriteExt}, net::TcpListener};

use log::{ info, debug, warn };

use crate::{parser::parse::Recipe, server::poll, watch::ProjectQueue};
use crate::server::close;
use crate::server::sync;

#[tokio::main]
pub async fn listen(address: Ipv4Addr, port: u16, queue: Arc<Mutex<ProjectQueue>>, recipe: Recipe) -> Result<(), std::io::Error> {
    let listener = TcpListener::bind((address, port)).await?;
    info!("Server is listening at \x1b[93m{address}:{port}");

        loop {
            let (socket, address) = listener.accept().await?;
            let recipe: Recipe = recipe.clone();
            let queue = queue.clone();

            tokio::spawn(async move {
                connection_handler(socket, address, &queue, recipe).await;
            });
        }
}

async fn connection_handler(mut socket: tokio::net::TcpStream, address: std::net::SocketAddr, queue: &Arc<Mutex<ProjectQueue>>, recipe: Recipe) {
    let mut reader = tokio::io::BufReader::new(&mut socket);
    let mut buffer = String::new();

    debug!("Incoming request from \x1b[93m{}", address);

    let mut line_count = 0;
    while reader.read_line(&mut buffer).await.unwrap() > 0 {
        if buffer.ends_with("\n\n") || buffer.ends_with("\n\r\n") {
            break;
        }

        line_count += 1;
    }

    debug!("Received header of size \x1b[93m{}\x1b[0m bytes with \x1b[93m{}\x1b[0m lines", buffer.len(), line_count);

    let bytes = buffer.as_bytes();
    let mut headers = vec![httparse::EMPTY_HEADER; line_count];
    let mut req = httparse::Request::new(&mut headers);
    let result = req.parse(&bytes).unwrap();

    if result.is_complete() {
        debug!("Received a complete request from \x1b[93m{}", address);
        match req.method.unwrap() {
            "PUT" => {
                socket.write_all(poll::process(headers, queue, recipe).as_bytes()).await.unwrap();
            },
            "DELETE" => {
                socket.write_all(close::process(headers)).await.unwrap();
            },
            "PATCH" => {
                socket.write_all(sync::process(headers, queue, recipe)).await.unwrap();
            },
            _ => {
                warn!("Received an unsupported request from \x1b[93m{}", address);
                socket.write_all(b"HTTP/1.1 404 Not Found\r\n\r\n").await.unwrap();
            }
        }

    } else {
        warn!("Client sent an incomplete request, closing connection");
    }
}