Extremely barebones IRC server project for learning Rust.
use crate::shutdown::Shutdown;
use log::info;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;

pub struct Service {
    control: Shutdown,
}

impl Service {
    pub fn new(control: Shutdown) -> Self {
        Self { control }
    }

    pub async fn serve(&mut self) -> Option<()> {
        info!("SERVICE: RUN");

        let communication_loop = tokio::spawn(async move {
            let listener = TcpListener::bind("127.0.0.1:8080").await.ok()?;

            loop {
                // Wait for incoming network request.
                // Dispatch it to the communicator and repeat.

                // This is ECHO server example from the Tokio dokumentation.
                let (mut socket, _) = listener.accept().await.ok()?;

                tokio::spawn(async move {
                    let mut buf = [0; 1024];

                    // In a loop, read data from the socket and write the data back.
                    loop {
                        let n = match socket.read(&mut buf).await {
                            // socket closed
                            Ok(n) if n == 0 => return Option::Some(()),
                            Ok(n) => n,
                            Err(e) => {
                                eprintln!("failed to read from socket; err = {:?}", e);
                                return Option::Some(());
                            }
                        };

                        // Write the data back
                        if let Err(e) = socket.write_all(&buf[0..n]).await {
                            eprintln!("failed to write to socket; err = {:?}", e);
                            return Option::Some(());
                        }
                    }
                });
            }

            // TODO: Needs some cleanup as this required by
            // compiler but does generate warning.
            Option::Some(())
        });

        self.control.recv().await;
        info!("SERVICE: RECEIVED CONTROL SIGNAL");

        communication_loop.abort();

        info!("COMMUNICATION: CANCELLED");
        info!("SERVICE: STOP");

        Option::Some(())
    }
}