Initial commit

Has the super barebones of a server

State API is next I think
This commit is contained in:
2026-05-13 12:27:13 -07:00
commit 1bd9555287
6 changed files with 2032 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
use std::fs::File;
use std::io::{Read,self};
use serde::{Serialize,Deserialize};
use thiserror::Error;
#[derive(Default,Clone,Serialize,Deserialize)]
pub struct Config {
pub hostname: String,
pub port: u16,
pub listen_address: String,
pub database: DBConfig,
pub certfile: String,
pub keyfile: String,
}
#[derive(Default,Clone,Serialize,Deserialize)]
pub struct DBConfig {
pub url: String,
pub user: String,
pub password: String,
}
const LOCATIONS: [&'static str; 3] = [
"confetti.toml",
"~/.config/confetti/confetti.toml",
"/etc/confetti/confetti.toml"
];
impl Config {
pub fn load() -> Result<Config,ConfigError> {
for filename in LOCATIONS {
match File::open(filename) {
Ok(mut f) => {
let mut buf = Vec::new();
f.read_to_end(&mut buf)?;
return Ok(toml::from_slice(&buf)?);
},
Err(_) => continue
}
}
Err(ConfigError::ConfigNotFound)
}
}
#[derive(Error, Debug)]
pub enum ConfigError {
#[error("Unable to find config file. Create a confetti.toml to run the application")]
ConfigNotFound,
#[error("Error while parsing config file: {0:?}")]
ParseError(#[from] toml::de::Error),
#[error("IO Error detected while processing config file")]
IOError(#[from] io::Error),
}
+80
View File
@@ -0,0 +1,80 @@
mod config;
use diesel::{Connection,PgConnection};
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::process::ExitCode;
use crate::config::Config;
#[tokio::main]
#[instrument]
async fn main() -> ExitCode {
// Read in config
let config = match Config::load() {
Ok(c) => c,
Err(e) => {
error!("Problem while reading config file");
error!("{:?}",e);
return ExitCode::FAILURE;
}
};
// Set up database connection
let db_connection = PgConnection::establish(&config.database.url);
// Read certificate file
let certs = CertificateDer::pem_file_iter(&config.certfile)
.unwrap()
.map(|cert| cert.unwrap())
.collect();
let key = PrivateKeyDer::from_pem_file(&config.keyfile).unwrap();
let address = match IpAddr::from_str(&config.listen_address) {
Ok(val) => val,
Err(e) => {
error!("Could not parse IP address: {:?}",e);
return ExitCode::FAILURE;
}
};
let quinn_config = match quinn::ServerConfig::with_single_cert(certs, key){
Ok(val) => val,
Err(e) => {
error!("Unable to intialize quinn server configuration: {:?}",e);
return ExitCode::FAILURE;
}
};
// Bind this endpoint to a UDP socket on the given server address.
let endpoint = match Endpoint::server(
quinn_config,
SocketAddr::new(address,config.port)
) {
Ok(val) => val,
Err(e) => {
error!("Could not create incoming socket");
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.
}
// Should never reach this
// How should I gracefully shutdown? Can I trap ctrlc
ExitCode::SUCCESS
}