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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
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]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -51,6 +62,12 @@ version = "0.2.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
|
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matches"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.29"
|
version = "0.10.29"
|
||||||
|
@ -78,6 +95,12 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "percent-encoding"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
|
@ -85,10 +108,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sheldon_director"
|
name = "sheldond"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"openssl",
|
"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]]
|
[[package]]
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sheldon_director"
|
name = "sheldond"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Klockenschooster <slartibartfast@klockenschooster.de>"]
|
authors = ["Klockenschooster <slartibartfast@klockenschooster.de>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
openssl = { version = "0.10" }
|
openssl = { version = "0.10" }
|
||||||
|
url = { version = "2.1" }
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Sheldon Director
|
Sheldon Director
|
||||||
================
|
================
|
||||||
|
|
||||||
A Gemini Server written in Rust.
|
A [Gemini](https://gemini.circumlunar.space/) Server written in Rust.
|
||||||
|
|
||||||
Why "Sheldon Director"?
|
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::net::{TcpListener, TcpStream, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
mod response;
|
use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype};
|
||||||
|
use url::Url;
|
||||||
|
mod server;
|
||||||
|
|
||||||
fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
|
fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
|
||||||
let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
|
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());
|
return Arc::new(acceptor.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_server() {
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_client(mut stream: SslStream<TcpStream>) {
|
fn handle_client(mut stream: SslStream<TcpStream>) {
|
||||||
let mut buffer = [0; 1026];
|
let mut buffer = [0; 1026];
|
||||||
stream.ssl_read(&mut buffer);
|
stream.ssl_read(&mut buffer);
|
||||||
let request = String::from_utf8(buffer.to_vec()).unwrap();
|
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 data = server::handle(&url);
|
||||||
let response = response::Response::new(header, [].to_vec());
|
|
||||||
|
|
||||||
stream.ssl_write(&response.format());
|
stream.ssl_write(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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