use std::{error::Error, net::SocketAddr, sync::Arc}; use connection::{connection_worker, Connections, RawConnection}; use giterated_daemon::{ authentication::AuthenticationTokenGranter, backend::{git::GitBackend, RepositoryBackend}, connection, listener, }; use listener::Listeners; use sqlx::{postgres::PgConnectOptions, ConnectOptions, PgPool}; use tokio::{ fs::File, io::{AsyncRead, AsyncReadExt, AsyncWrite}, net::{TcpListener, TcpStream}, sync::Mutex, }; use tokio_tungstenite::{accept_async, WebSocketStream}; use toml::Table; #[macro_use] extern crate tracing; #[tokio::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt::init(); let mut listener = TcpListener::bind("0.0.0.0:7270").await?; let connections: Arc> = Arc::default(); let listeners: Arc> = Arc::default(); let config: Table = { let mut file = File::open("Giterated.toml").await?; let mut text = String::new(); file.read_to_string(&mut text).await?; text.parse()? }; let db_conn_options = PgConnectOptions::new() .host(config["postgres"]["host"].as_str().unwrap()) .port(config["postgres"]["port"].as_integer().unwrap() as u16) .database(config["postgres"]["database"].as_str().unwrap()) .username(config["postgres"]["user"].as_str().unwrap()) .password(config["postgres"]["password"].as_str().unwrap()) .log_statements(log::LevelFilter::Off); let db_pool = PgPool::connect_with(db_conn_options).await?; debug!("Running database migrations..."); sqlx::migrate!().run(&db_pool).await?; info!("Connected"); let repository_backend: Arc> = Arc::new(Mutex::new({ let foo: GitBackend = GitBackend { pg_pool: db_pool, repository_folder: String::from("/tmp/foo"), }; foo })); let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter { config: config.clone(), })); info!("Connected"); loop { let stream = accept_stream(&mut listener).await; info!("Connected"); let (stream, address) = match stream { Ok(stream) => stream, Err(err) => { error!("Failed to accept connection. {:?}", err); continue; } }; info!("Accepted connection from {}", address); let connection = accept_websocket_connection(stream).await; let connection = match connection { Ok(connection) => connection, Err(err) => { error!( "Failed to initiate Websocket connection from {}. {:?}", address, err ); continue; } }; info!("Websocket connection established with {}", address); let connection = RawConnection { task: tokio::spawn(connection_worker( connection, listeners.clone(), connections.clone(), repository_backend.clone(), token_granter.clone(), address, )), }; connections.lock().await.connections.push(connection); } } async fn accept_stream( listener: &mut TcpListener, ) -> Result<(TcpStream, SocketAddr), Box> { let stream = listener.accept().await?; Ok(stream) } async fn accept_websocket_connection( stream: S, ) -> Result, Box> { let connection = accept_async(stream).await?; Ok(connection) }