architecture changes

This commit is contained in:
Jan Wolff 2020-05-16 11:03:48 +02:00
parent d5d2233896
commit 769affa1b6
5 changed files with 103 additions and 92 deletions

View file

@ -8,3 +8,6 @@ Why "Sheldon Director"?
Because it is the real name of that villain in _Kim Possible_ who went by the Because it is the real name of that villain in _Kim Possible_ who went by the
pseudonym "Gemini". (https://kimpossible.fandom.com/wiki/Gemini) pseudonym "Gemini". (https://kimpossible.fandom.com/wiki/Gemini)
Though you are free to imagine the shortened name stands for Sheldon Daemon.
But in that case you'll have to come up with your own explanation.

View file

@ -1,49 +1,6 @@
use std::net::{TcpListener, TcpStream, SocketAddr};
use std::sync::Arc;
use std::thread;
use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype};
use url::Url;
mod server; mod server;
fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
acceptor.set_private_key_file("doc/key.pem", SslFiletype::PEM).unwrap();
acceptor.set_certificate_chain_file("doc/cert.pem").unwrap();
acceptor.check_private_key().unwrap();
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 data = server::handle(&url);
stream.ssl_write(&data);
}
fn main() { fn main() {
let addrs = [ let server = server::Server::new("gemini://localhost");
SocketAddr::from(([127, 0, 0, 1], 1965)), server.serve();
];
let acceptor = build_acceptor();
let listener = TcpListener::bind(&addrs[..]).unwrap();
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let acceptor = acceptor.clone();
thread::spawn(move || {
let stream = acceptor.accept(stream).unwrap();
handle_client(stream);
});
}
Err(e) => { /* connection failed */ }
}
}
} }

View file

@ -1,16 +1,7 @@
use url::Url; use url::Url;
use crate::server::response::{Status, Header, Response}; use crate::server::response;
use crate::server::ServerConfig;
pub trait Handler { pub fn handle(config: &ServerConfig, url: Url) -> Option<response::Response> {
fn handle(&self, url : Url) -> Option<Response>; Some(response::invalid_protocol())
}
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()));
}
} }

View file

@ -1,30 +1,79 @@
use std::vec::Vec; use crate::server::response::Response;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod, SslStream};
use std::collections::HashMap; use std::collections::HashMap;
use std::net::{SocketAddr, TcpListener, TcpStream};
use std::thread;
use std::vec::Vec;
use std::sync::Arc;
use url::Url; use url::Url;
mod handler; pub mod response;
mod response; pub mod handler;
#[derive(Clone)]
pub struct ServerConfig {
defaultHost: Url,
}
pub struct Server { pub struct Server {
handlers: Vec<Box<dyn handler::Handler>>, acceptor: std::sync::Arc<SslAcceptor>,
config: ServerConfig,
} }
impl Server { impl Server {
pub fn new() -> Server { pub fn new(host: &str) -> Server {
Server{handlers: Vec::<Box<dyn handler::Handler>>::new()} let config = ServerConfig{defaultHost: Url::parse(host).unwrap()};
Server {
acceptor: build_acceptor(),
config: config,
}
}
pub fn serve(&self) {
let addrs = [SocketAddr::from(([127, 0, 0, 1], 1965))];
let listener = TcpListener::bind(&addrs[..]).unwrap();
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let acceptor = self.acceptor.clone();
let config = self.config.clone();
thread::spawn(move || {
let stream = acceptor.accept(stream).unwrap();
handle_client(&config, stream);
});
}
Err(e) => { /* connection failed */ }
}
}
} }
} }
pub fn register(host: &str, server: Server) { fn handle_client(config: &ServerConfig, mut stream: SslStream<TcpStream>) {
//// servers.insert( let mut buffer = [0; 1026];
//// host.to_string(), stream.ssl_read(&mut buffer);
//// server, let request = String::from_utf8(buffer.to_vec()).unwrap();
//// );
let location = match Url::parse(&request) {
Ok(url) => url,
Err(e) => config.defaultHost.join(&request).unwrap(),
};
let response = match handler::handle(config, location) {
Some(response) => response,
None => response::internal_error(),
};
stream.ssl_write(&response.format());
} }
pub fn handle(url: &Url) -> Vec<u8> { fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
return Vec::new(); let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
acceptor
.set_private_key_file("doc/key.pem", SslFiletype::PEM)
.unwrap();
acceptor.set_certificate_chain_file("doc/cert.pem").unwrap();
acceptor.check_private_key().unwrap();
return Arc::new(acceptor.build());
} }
//static mut servers : HashMap<String, Server> = HashMap::new();

View file

@ -2,12 +2,12 @@ use std::vec::Vec;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum Status { pub enum Status {
Input = 1, Input = 10,
Success = 2, Success = 20,
Redirect = 3, Redirect = 30,
TemporaryFailure = 4, TemporaryFailure = 40,
PermanentFailure = 5, PermanentFailure = 50,
ClientCertificateRequired = 6, ClientCertificateRequired = 60,
} }
pub struct Header { pub struct Header {
@ -22,28 +22,27 @@ pub struct Response {
impl Header { impl Header {
pub fn new(status: Status, meta: &str) -> Header { pub fn new(status: Status, meta: &str) -> Header {
Header{ Header {
status: status, status: status,
meta: meta.to_string(), meta: meta.to_string(),
} }
} }
pub fn format(&self) -> String { pub fn format(&self) -> String {
let status: u8 = self.status as u8; format!("{} {}\r\n", self.status as u8, self.meta)
return format!("{} {}\r\n", status * 10, self.meta)
} }
} }
impl Response { impl Response {
pub fn new(header: Header, data: Vec<u8>) -> Response { pub fn new(header: Header, data: Vec<u8>) -> Response {
Response{ Response {
header: header, header: header,
data: data, data: data,
} }
} }
pub fn new_empty(header: Header) -> Response { pub fn new_empty(header: Header) -> Response {
Response{ Response {
header: header, header: header,
data: Vec::new(), data: Vec::new(),
} }
@ -56,11 +55,23 @@ impl Response {
} }
} }
pub fn invalid_protocol () -> Response { pub fn invalid_protocol() -> Response {
Response::new_empty( Response::new_empty(Header::new(
Header::new(
Status::PermanentFailure, Status::PermanentFailure,
"this protocol is not supported" "this protocol is not supported",
), ))
) }
pub fn not_understood() -> Response {
Response::new_empty(Header::new(
Status::PermanentFailure,
"request not understood",
))
}
pub fn internal_error() -> Response {
Response::new_empty(Header::new(
Status::PermanentFailure,
"internal server error",
))
} }