diff --git a/.gitignore b/.gitignore index a617a21..8e38330 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ /target -/.env \ No newline at end of file +/config.json \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 20ee975..cbfd0b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,7 @@ dependencies = [ "parking_lot", "pin-project 0.4.27", "smallvec", - "tokio", + "tokio 0.2.25", "tokio-util 0.3.1", "trust-dns-proto", "trust-dns-resolver", @@ -48,7 +48,7 @@ dependencies = [ "futures-sink", "log", "pin-project 0.4.27", - "tokio", + "tokio 0.2.25", "tokio-util 0.3.1", ] @@ -195,7 +195,7 @@ dependencies = [ "futures-channel", "futures-util", "smallvec", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -715,12 +715,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - [[package]] name = "dtoa" version = "0.4.8" @@ -1016,7 +1010,7 @@ dependencies = [ "http", "indexmap", "slab", - "tokio", + "tokio 0.2.25", "tokio-util 0.3.1", "tracing", "tracing-futures", @@ -1210,15 +1204,14 @@ dependencies = [ "actix-web-actors", "base64", "clap", - "dotenv", "env_logger", - "futures", "lazy_static", "openssl", "rand 0.8.3", "serde", "serde_json", "sha1", + "tokio 1.5.0", ] [[package]] @@ -1657,7 +1650,7 @@ dependencies = [ "percent-encoding", "pin-project-lite 0.1.11", "sha1", - "tokio", + "tokio 0.2.25", "tokio-util 0.2.0", "url", ] @@ -2058,6 +2051,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "tokio" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5" +dependencies = [ + "autocfg", + "num_cpus", + "pin-project-lite 0.2.4", +] + [[package]] name = "tokio-openssl" version = "0.4.0" @@ -2065,7 +2069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c4b08c5f4208e699ede3df2520aca2e82401b2de33f45e96696a074480be594" dependencies = [ "openssl", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -2079,7 +2083,7 @@ dependencies = [ "futures-sink", "log", "pin-project-lite 0.1.11", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -2094,7 +2098,7 @@ dependencies = [ "futures-sink", "log", "pin-project-lite 0.1.11", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -2144,7 +2148,7 @@ dependencies = [ "rand 0.7.3", "smallvec", "thiserror", - "tokio", + "tokio 0.2.25", "url", ] @@ -2164,7 +2168,7 @@ dependencies = [ "resolv-conf", "smallvec", "thiserror", - "tokio", + "tokio 0.2.25", "trust-dns-proto", ] diff --git a/Cargo.toml b/Cargo.toml index 2b399c5..1edff19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,11 @@ description = "Chat app for lupt(लुप्त) users!" authors = ["Piyush Raj "] edition = "2018" license = "GPL 3.0" +license-file = "LICENSE" readme = "README.md" repository = "https://github.com/PiyushXCoder/lupt" +homepage = "luptchat.in" +categories = ["chatting-app"] keywords = ["chat","Chatting","Talk","Stranger"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -21,14 +24,13 @@ actix-ratelimit = "0.3.1" env_logger = "0.8.3" openssl = "0.10.28" -dotenv = "0.15.0" clap = "2.33.3" lazy_static = "1.4.0" serde = "1.0.123" serde_json = "1.0.62" rand = "0.8.3" -futures = "0.3.12" +tokio = { version = "1.5.0", features = ['rt', 'rt-multi-thread']} sha1 = "0.6.0" base64 = "0.13.0" diff --git a/src/config.rs b/src/config.rs index 3cad8ff..fb8eb23 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,23 +16,25 @@ */ use clap::{App, Arg}; +use serde::{Deserialize, Serialize}; + pub struct Config { pub static_path: String, - pub bind_address: String + pub bind_address: String, + pub config: ConfigFile +} + +#[derive(Serialize, Deserialize)] +pub struct ConfigFile { + pub salt: String, + pub tenor_key: String, + pub ssl_cert: String, + pub ssl_key: String, + pub logger_pattern: String } impl Config { pub fn new() -> Self { - let bind_address = std::env::var("URL"); - let static_path = std::env::var("STATIC_PATH"); - - if bind_address.is_ok() && static_path.is_ok() { - return Config { - static_path: static_path.unwrap(), - bind_address: bind_address.unwrap() - }; - } - let matches = App::new("Lupt (लुप्त)") .version(env!("CARGO_PKG_VERSION")) .author(env!("CARGO_PKG_AUTHORS")) @@ -51,11 +53,34 @@ impl Config { .help("Address to bind for server") .required(true) .takes_value(true)) + .arg(Arg::with_name("config") + .short("c") + .long("config") + .value_name("FILE") + .help("Path to config file") + .required(true) + .takes_value(true)) .get_matches(); + let conf = matches.value_of("config").unwrap().to_owned(); + let conf = std::fs::read_to_string(conf).expect("Failed to read config"); + + let config = serde_json::from_str::(&conf).expect(r" +Config File is corrupt. + +Config file must have following fields + - salt: Salt for hashing + - tenor_key: Key of tenor gif api + - ssl_cert: Path to certificate of ssl + - ssl_key: Path to private key of ssl + - logger_pattern: Pattern to make log according to Actix Logger +"); + + Config { static_path: matches.value_of("static_path").unwrap().to_owned(), - bind_address: matches.value_of("bind_address").unwrap().to_owned() + bind_address: matches.value_of("bind_address").unwrap().to_owned(), + config } } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 61b39c0..2af1bbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,8 +34,9 @@ use actix_web::{ use actix_files as fs; use actix_web_actors::ws; use actix_ratelimit::{RateLimiter, MemoryStore, MemoryStoreActor}; -use openssl::ssl::{SslConnector, SslMethod}; +use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslConnector, SslFiletype, SslMethod}; use ws_sansad::WsSansad; +use std::sync::RwLock; mod config; mod errors; @@ -45,19 +46,24 @@ mod chat_pinnd; mod validator; lazy_static! { - pub static ref SALT: String = std::env::var("SALT").unwrap(); - pub static ref TENOR_API_KEY: String = std::env::var("TENOR_API_KEY").unwrap(); + pub static ref SALT: RwLock = RwLock::new(String::new()); + pub static ref TENOR_API_KEY: RwLock = RwLock::new(String::new()); } #[actix_web::main] async fn main() -> std::io::Result<()> { - dotenv::dotenv().ok(); std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); let store = MemoryStore::new(); let config = config::Config::new(); + + *SALT.write().unwrap() = config.config.salt; + *TENOR_API_KEY.write().unwrap() = config.config.tenor_key; + + let ssl_builder = generate_ssl_builder(config.config.ssl_key, config.config.ssl_cert); + let logger_pattern = config.config.logger_pattern; let static_path = config.static_path; - HttpServer::new(move || { + let server = HttpServer::new(move || { App::new() .wrap( RateLimiter::new( @@ -65,14 +71,17 @@ async fn main() -> std::io::Result<()> { .with_interval(std::time::Duration::from_secs(60)) .with_max_requests(200) ) - .wrap(Logger::new("%t [%{x-forwarded-for}i] %s %{User-Agent}i %r")) + .wrap(Logger::new(&logger_pattern)) .service(web::resource("/ws/").route(web::get().to(ws_index))) .service(web::resource("/gif/{pos}/").route(web::get().to(gif))) .service(web::resource("/gif/{pos}/{query}").route(web::get().to(gif))) .service(fs::Files::new("/", &static_path).index_file("index.html")) - }) - .bind(config.bind_address)? - .run() + }); + + match ssl_builder { + Some(b) => server.bind_openssl(config.bind_address, b), + None => server.bind(config.bind_address) + }?.run() .await } @@ -91,7 +100,7 @@ async fn gif(req: HttpRequest) -> Result { .finish(); - let url = format!("https://g.tenor.com/v1/search?q={}&key={}&limit=20&media_filter=tinygif&pos={}", name.replace(" ", "+"), TENOR_API_KEY.to_owned(), pos); + let url = format!("https://g.tenor.com/v1/search?q={}&key={}&limit=20&media_filter=tinygif&pos={}", name.replace(" ", "+"), TENOR_API_KEY.read().unwrap(), pos); let response = client.get(url) .header("User-Agent", "actix-web/3.0") .send() @@ -100,4 +109,17 @@ async fn gif(req: HttpRequest) -> Result { .await?; Ok(HttpResponse::Ok().content_type("application/json").body(response)) +} + +fn generate_ssl_builder(key: String, cert: String) -> Option { + if key != "" && cert != "" { + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + builder + .set_private_key_file(key, SslFiletype::PEM) + .unwrap(); + builder.set_certificate_chain_file(cert).unwrap(); + Some(builder) + } else { + None + } } \ No newline at end of file diff --git a/src/ws_sansad/mod.rs b/src/ws_sansad/mod.rs index 0b986c2..bf7b3bb 100644 --- a/src/ws_sansad/mod.rs +++ b/src/ws_sansad/mod.rs @@ -58,7 +58,8 @@ impl Actor for WsSansad { } fn stopping(&mut self, _: &mut Self::Context) -> Running { - futures::executor::block_on(self.leave_kaksh()); // notify leaving + tokio::runtime::Runtime::new().unwrap() + .block_on(self.leave_kaksh());// notify leaving Running::Stop } } @@ -74,7 +75,8 @@ impl StreamHandler> for WsSansad { }, Ok(ws::Message::Pong(_)) => { self.hb = Instant::now(); }, Ok(ws::Message::Text(msg)) => { - futures::executor::block_on(self.parse_text_handle(msg)); + tokio::runtime::Runtime::new().unwrap() + .block_on(self.parse_text_handle(msg)); }, Ok(ws::Message::Close(msg)) => { ctx.close(msg); ctx.stop(); @@ -105,7 +107,8 @@ impl WsSansad { // heartbeat timed out // stop actor - futures::executor::block_on(act.leave_kaksh()); // notify leaving + tokio::runtime::Runtime::new().unwrap() + .block_on(act.leave_kaksh()); ctx.stop(); // don't try to send a ping return; diff --git a/src/ws_sansad/users.rs b/src/ws_sansad/users.rs index cf2e0bd..8c59fcc 100644 --- a/src/ws_sansad/users.rs +++ b/src/ws_sansad/users.rs @@ -46,7 +46,7 @@ impl WsSansad { } let mut m = sha1::Sha1::new(); m.update(format!("{}{}",kunjika, - crate::SALT.to_owned()).as_bytes()); + crate::SALT.read().unwrap()).as_bytes()); let kunjika = base64::encode(m.digest().bytes())[..8].to_owned(); // Name @@ -131,7 +131,7 @@ impl WsSansad { } let mut m = sha1::Sha1::new(); m.update(format!("{}{}",kunjika, - crate::SALT.to_owned()).as_bytes()); + crate::SALT.read().unwrap()).as_bytes()); let kunjika = base64::encode(m.digest().bytes())[..8].to_owned(); // Name