mod client_lib; use client_lib::*; mod client_net; use client_net::HyperNet; use curve25519_dalek::scalar::Scalar; use getopts::Options; use lox_library::bridge_table::BridgeLine; use lox_library::bridge_table::MAX_BRIDGES_PER_BUCKET; use lox_library::IssuerPubKey; use serde::Serialize; use std::env::args; use std::fs::File; use std::io::Write; use std::path::Path; use std::str::FromStr; // Prints the argument details for this program fn print_usage(program: &str, opts: Options) { let brief = format!("Usage: {} [options]", program); print!("{}", opts.usage(&brief)); } // Helper function to save serializable objects to files fn save_object(obj: T, filename: &str) { let mut outfile = File::create(filename).expect(&("Failed to create ".to_string() + filename)); write!(outfile, "{}", serde_json::to_string(&obj).unwrap()) .expect(&("Failed to write to ".to_string() + filename)); } #[tokio::main] async fn main() { let args: Vec = args().collect(); let mut opts = Options::new(); opts.optflag("h", "help", "print this help menu"); //#[cfg(test)] opts.optopt( "A", "advance-days", "increase server days by NUM_DAYS", "NUM_DAYS", ); opts.optflag("L", "level-up", "increase trust level"); opts.optflag("N", "new-lox-cred", "get a new Lox Credential"); opts.optopt( "", "server", "Lox Auth server address [http://localhost:8001]", "ADDR", ); let matches = match opts.parse(&args[1..]) { Ok(m) => m, Err(f) => { panic!("{}", f.to_string()) } }; if matches.opt_present("h") { print_usage(&args[0], opts); return; } let net = if matches.opt_present("server") { HyperNet { hostname: matches.opt_str("server").unwrap(), } } else { HyperNet { hostname: "http://localhost:8001".to_string(), } }; // Advance days on server (TESTING ONLY) //#[cfg(test)] if matches.opt_present("A") { let days: u16 = u16::from_str(matches.opt_str("A").unwrap().as_str()).unwrap(); let today: u32 = advance_days(&net, days).await; println!("Today's date according to the server: {}", today); } // Get Lox Authority public keys // TODO: Make this filename configurable let lox_auth_pubkeys_filename = "lox_auth_pubkeys.json"; let lox_auth_pubkeys: Vec = if Path::new(lox_auth_pubkeys_filename).exists() { // read in file let lox_auth_pubkeys_infile = File::open(lox_auth_pubkeys_filename).unwrap(); serde_json::from_reader(lox_auth_pubkeys_infile).unwrap() } else { // download from Lox Auth let pubkeys = get_lox_auth_keys(&net).await; // save to file for next time save_object(&pubkeys, &lox_auth_pubkeys_filename); pubkeys }; // Get Lox Credential and BridgeLine let lox_cred_filename = "lox_cred.json"; let bucket_filename = "bucket.json"; let (lox_cred, bucket) = if matches.opt_present("N") || !Path::new(lox_cred_filename).exists() || !Path::new(bucket_filename).exists() { // get new Lox Credential let open_invite = get_open_invitation(&net).await; let (cred, bl) = get_lox_credential(&net, &open_invite, get_lox_pub(&lox_auth_pubkeys)).await; let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; // note: this is a bucket with one real bridgeline and n-1 // default (zeroed out) bridgelines bucket[0] = bl; // save to files for next time save_object(&cred, &lox_cred_filename); save_object(&bucket, &bucket_filename); (cred, bucket) } else { // Read existing Lox Credential and BridgeLine from files let cred = serde_json::from_reader(File::open(lox_cred_filename).unwrap()).unwrap(); let bucket = serde_json::from_reader(File::open(bucket_filename).unwrap()).unwrap(); (cred, bucket) }; let lox_cred = if matches.opt_present("L") { let old_level = get_cred_trust_level(&lox_cred); // If trust level is 0, do trust promotion, otherwise level up. let cred = if old_level == 0 { if eligible_for_trust_promotion(&net, &lox_cred).await { let migration_cred = trust_promotion(&net, &lox_cred, get_lox_pub(&lox_auth_pubkeys)).await; let cred = trust_migration( &net, &lox_cred, &migration_cred, get_lox_pub(&lox_auth_pubkeys), get_migration_pub(&lox_auth_pubkeys), ) .await; cred } else { lox_cred } } else { if eligible_for_level_up(&net, &lox_cred).await { let encbuckets = get_reachability_credential(&net).await; let cred = level_up( &net, &lox_cred, &encbuckets, get_lox_pub(&lox_auth_pubkeys), get_reachability_pub(&lox_auth_pubkeys), ) .await; cred } else { lox_cred } }; save_object(&cred, &lox_cred_filename); let new_level = get_cred_trust_level(&cred); if new_level > old_level { println!("Old level: {}\nNew level: {}", old_level, new_level); } else if new_level == old_level { println!("Unable to level up. Current level: {}", new_level); } cred } else { lox_cred }; }