diff --git a/Cargo.lock b/Cargo.lock index 4f011ed..19bbbb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,6 +39,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -51,6 +62,12 @@ version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + [[package]] name = "openssl" version = "0.10.29" @@ -78,6 +95,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "pkg-config" version = "0.3.17" @@ -85,10 +108,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] -name = "sheldon_director" +name = "sheldond" version = "0.1.0" dependencies = [ "openssl", + "url", +] + +[[package]] +name = "smallvec" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +dependencies = [ + "smallvec", +] + +[[package]] +name = "url" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +dependencies = [ + "idna", + "matches", + "percent-encoding", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a0cec35..ab1b0c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] -name = "sheldon_director" +name = "sheldond" version = "0.1.0" authors = ["Klockenschooster "] edition = "2018" [dependencies] openssl = { version = "0.10" } +url = { version = "2.1" } diff --git a/README.md b/README.md index 0b960f6..2446406 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Sheldon Director ================ -A Gemini Server written in Rust. +A [Gemini](https://gemini.circumlunar.space/) Server written in Rust. Why "Sheldon Director"? ----------------------- diff --git a/src/main.rs b/src/main.rs index 8181b92..ab50c02 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ -use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype}; use std::net::{TcpListener, TcpStream, SocketAddr}; use std::sync::Arc; use std::thread; -mod response; +use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype}; +use url::Url; +mod server; fn build_acceptor() -> std::sync::Arc { let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap(); @@ -12,15 +13,18 @@ fn build_acceptor() -> std::sync::Arc { return Arc::new(acceptor.build()); } +fn build_server() { +} + fn handle_client(mut stream: SslStream) { let mut buffer = [0; 1026]; stream.ssl_read(&mut buffer); let request = String::from_utf8(buffer.to_vec()).unwrap(); + let url = Url::parse(&request).unwrap(); - let header = response::Header::new(response::Status::Success, "text/gemini".to_string()); - let response = response::Response::new(header, [].to_vec()); + let data = server::handle(&url); - stream.ssl_write(&response.format()); + stream.ssl_write(&data); } fn main() { diff --git a/src/response.rs b/src/response.rs deleted file mode 100644 index 521cad7..0000000 --- a/src/response.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::vec; - -#[derive(Copy, Clone)] -pub enum Status { - Input = 1, - Success = 2, - Redirect = 3, - TemporaryFailure = 4, - PermanentFailure = 5, - ClientCertificateRequired = 6, -} - -pub struct Header { - status: Status, - meta: String, -} - -pub struct Response { - header: Header, - data: std::vec::Vec, -} - -impl Header { - pub fn new(status: Status, meta: String) -> Header { - return Header{ - status: status, - meta: meta, - } - } - - pub fn format(&self) -> String { - let status: u8 = self.status as u8; - return format!("{} {}\r\n", status * 10, self.meta) - } -} - -impl Response { - pub fn new(header: Header, data: std::vec::Vec) -> Response { - return Response{ - header: header, - data: data, - } - } - - pub fn format(&self) -> std::vec::Vec { - let mut resp: std::vec::Vec = self.header.format().as_bytes().to_vec(); - resp.extend(&self.data); - return resp; - } -} diff --git a/src/server/handler.rs b/src/server/handler.rs new file mode 100644 index 0000000..ec4193d --- /dev/null +++ b/src/server/handler.rs @@ -0,0 +1,16 @@ +use url::Url; +use crate::server::response::{Status, Header, Response}; + +pub trait Handler { + fn handle(&self, url : Url) -> Option; +} + +pub struct TestHandler { +} + +impl Handler for TestHandler { + fn handle(&self, url : Url) -> Option { + let header = Header::new(Status::Success, "text/gemini"); + return Some(Response::new(header, Vec::new())); + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..01a686d --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,30 @@ +use std::vec::Vec; +use std::collections::HashMap; +use url::Url; + +mod handler; +mod response; + +pub struct Server { + handlers: Vec>, +} + +impl Server { + pub fn new() -> Server { + Server{handlers: Vec::>::new()} + } +} + +pub fn register(host: &str, server: Server) { +//// servers.insert( +//// host.to_string(), +//// server, +//// ); +} + +pub fn handle(url: &Url) -> Vec { + return Vec::new(); +} + +//static mut servers : HashMap = HashMap::new(); + diff --git a/src/server/response.rs b/src/server/response.rs new file mode 100644 index 0000000..f2df722 --- /dev/null +++ b/src/server/response.rs @@ -0,0 +1,66 @@ +use std::vec::Vec; + +#[derive(Copy, Clone)] +pub enum Status { + Input = 1, + Success = 2, + Redirect = 3, + TemporaryFailure = 4, + PermanentFailure = 5, + ClientCertificateRequired = 6, +} + +pub struct Header { + status: Status, + meta: String, +} + +pub struct Response { + header: Header, + data: Vec, +} + +impl Header { + pub fn new(status: Status, meta: &str) -> Header { + Header{ + status: status, + meta: meta.to_string(), + } + } + + pub fn format(&self) -> String { + let status: u8 = self.status as u8; + return format!("{} {}\r\n", status * 10, self.meta) + } +} + +impl Response { + pub fn new(header: Header, data: Vec) -> Response { + Response{ + header: header, + data: data, + } + } + + pub fn new_empty(header: Header) -> Response { + Response{ + header: header, + data: Vec::new(), + } + } + + pub fn format(&self) -> Vec { + let mut resp: Vec = self.header.format().as_bytes().to_vec(); + resp.extend(&self.data); + return resp; + } +} + +pub fn invalid_protocol () -> Response { + Response::new_empty( + Header::new( + Status::PermanentFailure, + "this protocol is not supported" + ), + ) +}