move to a modular design
This commit is contained in:
parent
d9e5170676
commit
d5d2233896
8 changed files with 184 additions and 58 deletions
61
Cargo.lock
generated
61
Cargo.lock
generated
|
@ -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]]
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
[package]
|
||||
name = "sheldon_director"
|
||||
name = "sheldond"
|
||||
version = "0.1.0"
|
||||
authors = ["Klockenschooster <slartibartfast@klockenschooster.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
openssl = { version = "0.10" }
|
||||
url = { version = "2.1" }
|
||||
|
||||
|
|
|
@ -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"?
|
||||
-----------------------
|
||||
|
|
14
src/main.rs
14
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<SslAcceptor> {
|
||||
let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
|
||||
|
@ -12,15 +13,18 @@ fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
|
|||
return Arc::new(acceptor.build());
|
||||
}
|
||||
|
||||
fn build_server() {
|
||||
}
|
||||
|
||||
fn handle_client(mut stream: SslStream<TcpStream>) {
|
||||
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() {
|
||||
|
|
|
@ -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<u8>,
|
||||
}
|
||||
|
||||
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<u8>) -> Response {
|
||||
return Response{
|
||||
header: header,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format(&self) -> std::vec::Vec<u8> {
|
||||
let mut resp: std::vec::Vec<u8> = self.header.format().as_bytes().to_vec();
|
||||
resp.extend(&self.data);
|
||||
return resp;
|
||||
}
|
||||
}
|
16
src/server/handler.rs
Normal file
16
src/server/handler.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use url::Url;
|
||||
use crate::server::response::{Status, Header, Response};
|
||||
|
||||
pub trait Handler {
|
||||
fn handle(&self, url : Url) -> Option<Response>;
|
||||
}
|
||||
|
||||
pub struct TestHandler {
|
||||
}
|
||||
|
||||
impl Handler for TestHandler {
|
||||
fn handle(&self, url : Url) -> Option<Response> {
|
||||
let header = Header::new(Status::Success, "text/gemini");
|
||||
return Some(Response::new(header, Vec::new()));
|
||||
}
|
||||
}
|
30
src/server/mod.rs
Normal file
30
src/server/mod.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use std::vec::Vec;
|
||||
use std::collections::HashMap;
|
||||
use url::Url;
|
||||
|
||||
mod handler;
|
||||
mod response;
|
||||
|
||||
pub struct Server {
|
||||
handlers: Vec<Box<dyn handler::Handler>>,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn new() -> Server {
|
||||
Server{handlers: Vec::<Box<dyn handler::Handler>>::new()}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(host: &str, server: Server) {
|
||||
//// servers.insert(
|
||||
//// host.to_string(),
|
||||
//// server,
|
||||
//// );
|
||||
}
|
||||
|
||||
pub fn handle(url: &Url) -> Vec<u8> {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
//static mut servers : HashMap<String, Server> = HashMap::new();
|
||||
|
66
src/server/response.rs
Normal file
66
src/server/response.rs
Normal file
|
@ -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<u8>,
|
||||
}
|
||||
|
||||
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<u8>) -> Response {
|
||||
Response{
|
||||
header: header,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_empty(header: Header) -> Response {
|
||||
Response{
|
||||
header: header,
|
||||
data: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format(&self) -> Vec<u8> {
|
||||
let mut resp: Vec<u8> = 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"
|
||||
),
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue