Lots more plumbing
Focusing mostly on getting main in shape and figuring out how to make the connections flow. The main is pretty much there, going to be a bit more when I take a shot at federation.
This commit is contained in:
+118
-13
@@ -1,16 +1,29 @@
|
||||
mod client;
|
||||
mod config;
|
||||
mod connection;
|
||||
mod state;
|
||||
|
||||
use diesel::{Connection,PgConnection};
|
||||
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
|
||||
use diesel_async::pooled_connection::deadpool::Pool;
|
||||
use diesel_async::{AsyncConnection,AsyncPgConnection};
|
||||
use quinn::rustls::pki_types::{PrivateKeyDer,CertificateDer,pem::PemObject};
|
||||
|
||||
use std::net::{IpAddr,SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use quinn::Endpoint;
|
||||
use tracing::{error,instrument};
|
||||
|
||||
|
||||
use std::io;
|
||||
use std::fs;
|
||||
use std::net::{IpAddr,SocketAddr};
|
||||
use std::process::ExitCode;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use serde::{Deserialize,Serialize};
|
||||
use tracing::{error,instrument,warn,debug};
|
||||
use tokio::sync::{RwLock,broadcast,mpsc};
|
||||
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::state::State;
|
||||
|
||||
#[derive(Hash,Eq,PartialEq,Clone,Serialize,Deserialize)]
|
||||
pub struct Coordinate(Vec<i64>);
|
||||
|
||||
#[tokio::main]
|
||||
#[instrument]
|
||||
@@ -22,12 +35,19 @@ async fn main() -> ExitCode {
|
||||
error!("Problem while reading config file");
|
||||
error!("{:?}",e);
|
||||
return ExitCode::FAILURE;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Set up database connection
|
||||
let db_connection = PgConnection::establish(&config.database.url);
|
||||
let db_config = AsyncDieselConnectionManager::<diesel_async::AsyncPgConnection>::new(config.database.url.clone());
|
||||
let db_pool = match Pool::builder(db_config).build() {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
error!("Error while creating database connection pool");
|
||||
error!("{:?}",e);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Read certificate file
|
||||
@@ -66,14 +86,99 @@ async fn main() -> ExitCode {
|
||||
}
|
||||
};
|
||||
|
||||
// Load or create new state
|
||||
let state = match State::load_from_file(&config.statefile) {
|
||||
Ok(state) => state,
|
||||
// Create file if it does not exist
|
||||
Err(e) => {
|
||||
match e.kind() {
|
||||
io::ErrorKind::NotFound => {
|
||||
match fs::File::create(&config.statefile) {
|
||||
// If the statefile is writable then create an empty state
|
||||
// and use that
|
||||
Ok(_) => State::new(),
|
||||
Err(e) => {
|
||||
error!("Could not open or create statefile. Check your config.");
|
||||
error!("{:?}",e);
|
||||
return ExitCode::FAILURE;
|
||||
|
||||
// Start iterating over incoming connections.
|
||||
while let Some(conn) = endpoint.accept().await {
|
||||
let connection = conn.await;
|
||||
}
|
||||
}
|
||||
|
||||
// Save connection somewhere, start transferring, receiving data, see DataTransfer tutorial.
|
||||
},
|
||||
_ => {
|
||||
error!("Could not open or create statefile. Check your config.");
|
||||
error!("{:?}",e);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
let statehandle = Arc::new(RwLock::new(state));
|
||||
|
||||
// Global connections
|
||||
let (close_send,close_recv) = broadcast::channel(1);
|
||||
let (message_send,message_recv) = broadcast::channel(128);
|
||||
let (message_ack_send,message_ack_recv) = mpsc::channel(128);
|
||||
|
||||
match ctrlc_async::set_async_handler(
|
||||
async move { match close_send.send(()) {
|
||||
Ok(_val) => (),
|
||||
Err(e) => {
|
||||
error!("Shutdown handler is broken. Cannot gracefully exit.");
|
||||
error!("{:?}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Ok(()) => (),
|
||||
Err(e) => {
|
||||
error!("Could not set up signal handler");
|
||||
error!("{:?}",e);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
let mut join_handles = Vec::new();
|
||||
|
||||
// Create client listener
|
||||
|
||||
let statehandle_cloned = statehandle.clone();
|
||||
join_handles.push(tokio::spawn(async move {
|
||||
connection::client_handler(
|
||||
statehandle_cloned,
|
||||
(message_send.clone(),message_recv.resubscribe()),
|
||||
message_ack_send,
|
||||
db_pool,
|
||||
endpoint,
|
||||
close_recv.resubscribe()
|
||||
).await;
|
||||
} ));
|
||||
|
||||
// Wait for child threads to exit
|
||||
for handle in join_handles {
|
||||
match handle.await {
|
||||
Ok(()) => (),
|
||||
Err(e) => {
|
||||
warn!("Problem while cleaning up threads");
|
||||
warn!("{:?}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Save state
|
||||
match statehandle.write().await.write_to_file(&config.statefile) {
|
||||
Ok(()) => debug!("Successfully wrote state to {:?}",config.statefile),
|
||||
Err(e) => {
|
||||
error!("Problem while writing to statefile");
|
||||
error!("{:?}",e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Should never reach this
|
||||
// How should I gracefully shutdown? Can I trap ctrlc
|
||||
ExitCode::SUCCESS
|
||||
|
||||
Reference in New Issue
Block a user