Implement server networking.
This commit is contained in:
parent
329b97be9f
commit
26fe6c86e7
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
*.pem
|
||||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = "0.2.92"
|
wasm-bindgen = "0.2.92"
|
||||||
|
@ -8,7 +8,7 @@ pub struct App {
|
|||||||
|
|
||||||
pub document:web_sys::Document,
|
pub document:web_sys::Document,
|
||||||
pub menu:web_sys::Element,
|
pub menu:web_sys::Element,
|
||||||
pub container:web_sys::Element,
|
pub main:web_sys::Element,
|
||||||
|
|
||||||
unload:Option<fn()>,
|
unload:Option<fn()>,
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ impl App {
|
|||||||
|
|
||||||
document:document,
|
document:document,
|
||||||
menu:menu.unwrap(),
|
menu:menu.unwrap(),
|
||||||
container:container.unwrap(),
|
main:container.unwrap(),
|
||||||
|
|
||||||
unload:None,
|
unload:None,
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
scene::util,
|
scene::{ui, util},
|
||||||
|
session::SessionState,
|
||||||
APP,
|
APP,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -14,9 +15,63 @@ impl crate::prelude::Scene for SceneListOnline {
|
|||||||
{
|
{
|
||||||
let mut app = unsafe {APP.borrow_mut()};
|
let mut app = unsafe {APP.borrow_mut()};
|
||||||
match &mut *app {
|
match &mut *app {
|
||||||
Some(_app) => {
|
Some(app) => {
|
||||||
util::load_mainmenu();
|
util::load_mainmenu();
|
||||||
|
|
||||||
|
// Create header
|
||||||
|
match app.document.create_element("header") {
|
||||||
|
Ok(header) => {
|
||||||
|
|
||||||
|
// Left-side header
|
||||||
|
match app.document.create_element("section") {
|
||||||
|
Ok(section_left) => {
|
||||||
|
|
||||||
|
// Button: Start
|
||||||
|
if app.session.state == SessionState::User {
|
||||||
|
match ui::button(&app.document, "Start", |_e|{ }) {
|
||||||
|
Ok(button) => { section_left.append_child(&button).ok(); }
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header.append_child(§ion_left).ok();
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right-side header
|
||||||
|
match app.document.create_element("section") {
|
||||||
|
Ok(section_right) => {
|
||||||
|
|
||||||
|
// Button: Previous Page
|
||||||
|
match ui::button(&app.document, "◀", |_e|{ }) {
|
||||||
|
Ok(button) => { section_right.append_child(&button).ok(); }
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text: Page Number
|
||||||
|
match ui::button(&app.document, "", |_e|{ }) {
|
||||||
|
Ok(elem) => {
|
||||||
|
elem.set_id("pn");
|
||||||
|
section_right.append_child(&elem).ok();
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button: Next Page
|
||||||
|
match ui::button(&app.document, "▶", |_e|{ }) {
|
||||||
|
Ok(button) => { section_right.append_child(&button).ok(); }
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
app.main.append_child(&header).ok();
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => { }
|
None => { }
|
||||||
}
|
}
|
||||||
|
@ -14,3 +14,14 @@ pub fn button(document:&web_sys::Document, text:&str, callback:fn(web_sys::Event
|
|||||||
Err(_) => Err(())
|
Err(_) => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn text_block(document:&web_sys::Document, text:&str) -> Result<web_sys::Element,()>
|
||||||
|
{
|
||||||
|
match document.create_element("div") {
|
||||||
|
Ok(element) => {
|
||||||
|
element.set_text_content(Some(text));
|
||||||
|
Ok(element)
|
||||||
|
}
|
||||||
|
Err(_) => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ use crate::util::{pack_u16, unpack_u16};
|
|||||||
|
|
||||||
use super::Packet;
|
use super::Packet;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PacketAuth {
|
pub struct PacketAuth {
|
||||||
pub handle:String,
|
pub handle:String,
|
||||||
pub secret:String,
|
pub secret:String,
|
||||||
@ -62,6 +63,7 @@ impl Packet for PacketAuth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PacketAuthResponse {
|
pub struct PacketAuthResponse {
|
||||||
pub status:bool,
|
pub status:bool,
|
||||||
pub token:[u8; 8],
|
pub token:[u8; 8],
|
||||||
|
@ -7,4 +7,4 @@ mod prelude {
|
|||||||
fn encode(&self) -> Vec<u8>;
|
fn encode(&self) -> Vec<u8>;
|
||||||
fn decode(data:&Vec<u8>, index:&mut usize) -> Result<Self::Data, ()>;
|
fn decode(data:&Vec<u8>, index:&mut usize) -> Result<Self::Data, ()>;
|
||||||
}
|
}
|
||||||
} use prelude::*;
|
} pub use prelude::*;
|
||||||
|
@ -8,12 +8,16 @@ tokio = { version = "1.39.2", features = ["full"] }
|
|||||||
tokio-stream = "0.1.15"
|
tokio-stream = "0.1.15"
|
||||||
tokio-tungstenite = "0.23.1"
|
tokio-tungstenite = "0.23.1"
|
||||||
tokio-rustls = "0.26.0"
|
tokio-rustls = "0.26.0"
|
||||||
|
tokio-util = { version = "0.7.11", features = ["compat"] }
|
||||||
rustls = "0.23.5"
|
rustls = "0.23.5"
|
||||||
rustls-pemfile = "2.1.2"
|
rustls-pemfile = "2.1.2"
|
||||||
webpki-roots = "0.26"
|
webpki-roots = "0.26"
|
||||||
opaque-ke = "2.0.0"
|
opaque-ke = "2.0.0"
|
||||||
|
hyper = { version = "1.4.1", features = ["full"] }
|
||||||
|
hyper-util = { version = "0.1.7", features = ["tokio"] }
|
||||||
|
|
||||||
game = { path = "../game" }
|
game = { path = "../game" }
|
||||||
|
|
||||||
bus = { git = "https://git.tsukiyo.org/Utility/bus" }
|
bus = { git = "https://git.tsukiyo.org/Utility/bus" }
|
||||||
trie = { git = "https://git.tsukiyo.org/Utility/trie" }
|
trie = { git = "https://git.tsukiyo.org/Utility/trie" }
|
||||||
|
pool = { git = "https://git.tsukiyo.org/Utility/pool" }
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
use game::Game;
|
use game::Game;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
pub struct Contest {
|
||||||
pub struct User {
|
|
||||||
id:usize,
|
|
||||||
online:bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Match {
|
|
||||||
game:Game,
|
game:Game,
|
||||||
|
|
||||||
p_dawn:u64,
|
p_dawn:u64,
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
use game::util::pack_u32;
|
||||||
|
use pool::Pool;
|
||||||
|
use trie::Trie;
|
||||||
|
|
||||||
pub mod user; use user::User;
|
pub mod user; use user::User;
|
||||||
pub mod session; use session::Session;
|
pub mod session; use session::Session;
|
||||||
pub mod contest; use contest::Contest;
|
pub mod contest; use contest::Contest;
|
||||||
@ -5,6 +9,7 @@ pub mod context;
|
|||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
users:Pool<User>,
|
users:Pool<User>,
|
||||||
|
handles:Trie<u32>,
|
||||||
salts:Vec<[u8; 16]>,
|
salts:Vec<[u8; 16]>,
|
||||||
sessions:Pool<Session>,
|
sessions:Pool<Session>,
|
||||||
contests:Pool<Contest>,
|
contests:Pool<Contest>,
|
||||||
@ -14,6 +19,7 @@ impl App {
|
|||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
users:Pool::new(),
|
users:Pool::new(),
|
||||||
|
handles:Trie::new(),
|
||||||
salts:Vec::new(),
|
salts:Vec::new(),
|
||||||
sessions:Pool::new(),
|
sessions:Pool::new(),
|
||||||
contests:Pool::new(),
|
contests:Pool::new(),
|
||||||
@ -26,10 +32,13 @@ impl App {
|
|||||||
let path_data = Path::new("data");
|
let path_data = Path::new("data");
|
||||||
if !path_data.exists() {
|
if !path_data.exists() {
|
||||||
fs::create_dir(path_data)?;
|
fs::create_dir(path_data)?;
|
||||||
fs::create_dir(path_data.join("session"))?;
|
fs::create_dir(path_data.join("c"))?;
|
||||||
fs::create_dir(path_data.join("user"))?;
|
fs::create_dir(path_data.join("s"))?;
|
||||||
|
fs::create_dir(path_data.join("u"))?;
|
||||||
|
|
||||||
fs::write(path_data.join("user/index"), pack_u32(0));
|
fs::write(path_data.join("c/.i"), pack_u32(0)).ok();
|
||||||
|
fs::write(path_data.join("s/.i"), pack_u32(0)).ok();
|
||||||
|
fs::write(path_data.join("u/.i"), pack_u32(0)).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -10,7 +10,7 @@ impl Session {
|
|||||||
pub fn new() -> Self
|
pub fn new() -> Self
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
key:[0; 8],
|
key:0,
|
||||||
secret:[0; 16],
|
secret:[0; 16],
|
||||||
user:None,
|
user:None,
|
||||||
context:Context::None,
|
context:Context::None,
|
||||||
|
@ -8,12 +8,12 @@ mod system;
|
|||||||
mod protocol;
|
mod protocol;
|
||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
use net::Server;
|
use system::{cache::WebCache, net::Stream};
|
||||||
use protocol::QRPacket;
|
use tokio_stream::StreamExt;
|
||||||
|
use tokio_tungstenite::WebSocketStream;
|
||||||
struct ServiceArgs {
|
use hyper_util::rt::TokioIo;
|
||||||
bus:Bus<protocol::QRPacket>,
|
use tokio_rustls::server::TlsStream;
|
||||||
}
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
async fn thread_datasystem(mut _app:App, bus:Bus<protocol::QRPacket>)
|
async fn thread_datasystem(mut _app:App, bus:Bus<protocol::QRPacket>)
|
||||||
{
|
{
|
||||||
@ -23,8 +23,8 @@ async fn thread_datasystem(mut _app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
while match bus.receive_wait() {
|
while match bus.receive_wait() {
|
||||||
Some(packet) => {
|
Some(packet) => {
|
||||||
match packet.data {
|
match packet.data {
|
||||||
QRPacket::QAuthenticate(request) => {
|
QRPacket::QAuth(_request) => {
|
||||||
let mut response = PacketAuthResponse::new();
|
let response = PacketAuthResponse::new();
|
||||||
|
|
||||||
// get user id from handle
|
// get user id from handle
|
||||||
|
|
||||||
@ -44,33 +44,126 @@ async fn thread_datasystem(mut _app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
} { }
|
} { }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_tcp(stream:net::tls::TlsStream, addr:SocketAddr, args:SericeArgs)
|
#[derive(Clone)]
|
||||||
|
struct HttpServiceArgs {
|
||||||
|
bus:Bus<protocol::QRPacket>,
|
||||||
|
cache:WebCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_ws(mut ws_stream:WebSocketStream<TlsStream<TcpStream>>, args:HttpServiceArgs)
|
||||||
{
|
{
|
||||||
use game::util::unpack_u32;
|
use tokio_tungstenite::tungstenite::protocol::Message;
|
||||||
|
use game::util::unpack_u16;
|
||||||
|
use protocol::QRPacket;
|
||||||
|
use game::protocol::{
|
||||||
|
code::*,
|
||||||
|
packet::*,
|
||||||
|
};
|
||||||
|
|
||||||
let length = vec![0u8; 4];
|
let bus_ds = args.bus.mailbox(1).unwrap_or(1);
|
||||||
match stream.recv(&mut length) {
|
|
||||||
Ok(4) => {
|
while match ws_stream.try_next().await {
|
||||||
let buffer = Vec::<u8>::with_capacity(unpack_u32(&length, &mut 0) as usize);
|
Ok(msg) => match msg {
|
||||||
match stream.recv(&mut buffer) {
|
Some(Message::Binary(data)) => {
|
||||||
|
|
||||||
|
let mut index :usize = 0;
|
||||||
|
let code: u16 = unpack_u16(&data, &mut index);
|
||||||
|
|
||||||
|
match code {
|
||||||
|
CODE_AUTH => {
|
||||||
|
match PacketAuth::decode(&data, &mut index) {
|
||||||
|
Ok(packet) => {
|
||||||
|
if args.bus.send(bus_ds, QRPacket::QAuth(packet)).is_ok() {
|
||||||
|
match args.bus.receive_wait() {
|
||||||
|
Some(resp) => match resp.data {
|
||||||
|
QRPacket::RAuth(_resp) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
_ => { }
|
||||||
|
}
|
||||||
|
None => { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(_) => {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(_) => { }
|
Err(_) => { }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_ => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Some(_) => true,
|
||||||
|
None => false
|
||||||
|
}
|
||||||
|
Err(_) => false,
|
||||||
|
} { }
|
||||||
|
|
||||||
|
ws_stream.close(None).await.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn service_http(request:hyper::Request<hyper::body::Incoming>, args:HttpServiceArgs) -> Result<hyper::Response<String>, std::convert::Infallible>
|
||||||
|
{
|
||||||
|
use hyper::Response;
|
||||||
|
use tokio_tungstenite::accept_async;
|
||||||
|
|
||||||
|
match request.uri().path() {
|
||||||
|
"" => Ok(Response::new(args.cache.html())),
|
||||||
|
".css" => Ok(Response::new(args.cache.css())),
|
||||||
|
".js" => Ok(Response::new(args.cache.js())),
|
||||||
|
".wasm" => Ok(Response::new(args.cache.wasm())),
|
||||||
|
//"favicon.png" => Ok(Response::new(String::new())),
|
||||||
|
"ws" => {
|
||||||
|
if request.headers().get(hyper::header::UPGRADE).map(|h| h == "websocket").unwrap_or(false) {
|
||||||
|
match hyper::upgrade::on(request).await {
|
||||||
|
Ok(upgraded) => {
|
||||||
|
match upgraded.downcast::<TokioIo<TlsStream<TcpStream>>>() {
|
||||||
|
Ok(parts) => {
|
||||||
|
match accept_async(parts.io.into_inner()).await {
|
||||||
|
Ok(ws_stream) => { handle_ws(ws_stream, args).await }
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(101)
|
||||||
|
.header(hyper::header::UPGRADE, "websocket")
|
||||||
|
.body(String::new())
|
||||||
|
.unwrap())
|
||||||
|
}
|
||||||
|
_ => Ok(Response::new(String::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_http(stream:system::net::tls::TlsStream, addr:SocketAddr, args:HttpServiceArgs) -> Result<(),()>
|
||||||
|
{
|
||||||
|
use hyper::server::conn::http1;
|
||||||
|
use hyper::service::service_fn;
|
||||||
|
|
||||||
|
println!("Connection from {}", addr.to_string());
|
||||||
|
|
||||||
|
let io = TokioIo::new(stream.to_stream());
|
||||||
|
|
||||||
|
http1::Builder::new()
|
||||||
|
.serve_connection(io, service_fn(move |req| {
|
||||||
|
service_http(req, args.clone())
|
||||||
|
}))
|
||||||
|
.await.ok();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main()
|
async fn main()
|
||||||
{
|
{
|
||||||
use system::net::{
|
use system::net::{
|
||||||
|
Server,
|
||||||
tls::*,
|
tls::*,
|
||||||
certstore::CertStore,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize application data.
|
// Initialize application data.
|
||||||
@ -81,17 +174,13 @@ async fn main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initialize service data.
|
|
||||||
//let cs = CertStore::new();
|
|
||||||
//cs.add("omen.kirisame.com", "cert/fullchain.pem", "cert/privkey.pem").ok();
|
|
||||||
//let cs = cs.to_share();
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize central bus and data serivce.
|
// Initialize central bus and data serivce.
|
||||||
let bus = Bus::<protocol::QRPacket>::new_as(bus::Mode::Transmitter);
|
let b_main :Bus<protocol::QRPacket> = Bus::new_as(bus::Mode::Transmitter);
|
||||||
match bus.connect() {
|
match b_main.connect() {
|
||||||
Ok(bus) => {
|
Ok(bus) => {
|
||||||
tokio::spawn(move || { thread_datasystem(app, bus); });
|
tokio::spawn(async move {
|
||||||
|
thread_datasystem(app, bus).await;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("fatal: failed to initialize bus.");
|
println!("fatal: failed to initialize bus.");
|
||||||
@ -101,24 +190,30 @@ async fn main()
|
|||||||
|
|
||||||
|
|
||||||
// Initialize HTTPS service.
|
// Initialize HTTPS service.
|
||||||
match bus.connect() {
|
match b_main.connect() {
|
||||||
Ok(bus) => {
|
Ok(bus) => {
|
||||||
// bind 38611
|
let cache = WebCache::init();
|
||||||
|
|
||||||
|
let mut server = TlsServer::new();
|
||||||
|
server.add_cert("omen.kirisame.com", "cert/fullchain.pem", "cert/privkey.pem").await.ok();
|
||||||
|
match server.bind("0.0.0.0:38612").await {
|
||||||
|
Ok(_) => {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while server.accept(handle_http, HttpServiceArgs {
|
||||||
|
bus:bus.connect().unwrap(),
|
||||||
|
cache:cache.clone(),
|
||||||
|
}).await.is_ok() { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
println!("error: failed to bind port 38612.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("error: failed to initialize HTTPS service.");
|
println!("error: failed to initialize HTTPS service.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize TLS service.
|
|
||||||
match bus.connect() {
|
|
||||||
Ok(bus) => {
|
|
||||||
// bind 38612
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
println!("error: failed to initialize TLS service.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::thread::park();
|
std::thread::park();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use game::protocol::packet::*;
|
use game::protocol::packet::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum QRPacket {
|
pub enum QRPacket {
|
||||||
QAuth(PacketAuth),
|
QAuth(PacketAuth),
|
||||||
RAuth(PacketAuthResponse),
|
RAuth(PacketAuthResponse),
|
||||||
|
100
server/src/system/cache/mod.rs
vendored
Normal file
100
server/src/system/cache/mod.rs
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use std::{io::Read, sync::{Arc, RwLock}};
|
||||||
|
|
||||||
|
use crate::util::string::minimize_whitespace;
|
||||||
|
|
||||||
|
struct WebCacheData {
|
||||||
|
html:String,
|
||||||
|
css:String,
|
||||||
|
js:String,
|
||||||
|
wasm:String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct WebCache {
|
||||||
|
data:Arc<RwLock<WebCacheData>>,
|
||||||
|
}
|
||||||
|
impl WebCache {
|
||||||
|
pub fn init() -> Self
|
||||||
|
{
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
let mut html = String::new();
|
||||||
|
let mut css = String::new();
|
||||||
|
let mut js = String::new();
|
||||||
|
let mut wasm = String::new();
|
||||||
|
|
||||||
|
// Cache html file
|
||||||
|
match File::open("www/.html") {
|
||||||
|
Ok(mut file) => {
|
||||||
|
file.read_to_string(&mut html).ok();
|
||||||
|
html = minimize_whitespace(&html);
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache css file
|
||||||
|
match File::open("www/.css") {
|
||||||
|
Ok(mut file) => {
|
||||||
|
file.read_to_string(&mut css).ok();
|
||||||
|
css = minimize_whitespace(&css);
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache js file
|
||||||
|
match File::open("www/.js") {
|
||||||
|
Ok(mut file) => {
|
||||||
|
file.read_to_string(&mut js).ok();
|
||||||
|
js = minimize_whitespace(&js);
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache wasm file
|
||||||
|
match File::open("www/.wasm") {
|
||||||
|
Ok(mut file) => {
|
||||||
|
file.read_to_string(&mut wasm).ok();
|
||||||
|
wasm = minimize_whitespace(&wasm);
|
||||||
|
}
|
||||||
|
Err(_) => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
data:Arc::new(RwLock::new(WebCacheData {
|
||||||
|
html, css, js, wasm
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn html(&self) -> String
|
||||||
|
{
|
||||||
|
match self.data.read() {
|
||||||
|
Ok(reader) => reader.html.to_string(),
|
||||||
|
Err(_) => String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn css(&self) -> String
|
||||||
|
{
|
||||||
|
match self.data.read() {
|
||||||
|
Ok(reader) => reader.css.to_string(),
|
||||||
|
Err(_) => String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn js(&self) -> String
|
||||||
|
{
|
||||||
|
match self.data.read() {
|
||||||
|
Ok(reader) => reader.js.to_string(),
|
||||||
|
Err(_) => String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wasm(&self) -> String
|
||||||
|
{
|
||||||
|
match self.data.read() {
|
||||||
|
Ok(reader) => reader.wasm.to_string(),
|
||||||
|
Err(_) => String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,4 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
pub mod net;
|
pub mod net;
|
||||||
|
pub mod cache;
|
||||||
|
@ -7,6 +7,7 @@ pub trait Stream {
|
|||||||
fn recv(&mut self, buffer:&mut [u8]) -> Result<usize, ()>;
|
fn recv(&mut self, buffer:&mut [u8]) -> Result<usize, ()>;
|
||||||
fn send(&mut self, buffer:&mut [u8]) -> Result<(), ()>;
|
fn send(&mut self, buffer:&mut [u8]) -> Result<(), ()>;
|
||||||
fn stream(&mut self) -> &mut Self::Socket;
|
fn stream(&mut self) -> &mut Self::Socket;
|
||||||
|
fn to_stream(self) -> Self::Socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Server {
|
pub trait Server {
|
||||||
|
@ -19,6 +19,10 @@ impl Stream for TcpStream {
|
|||||||
fn stream(&mut self) -> &mut Self::Socket {
|
fn stream(&mut self) -> &mut Self::Socket {
|
||||||
&mut self.stream
|
&mut self.stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_stream(self) -> Self::Socket {
|
||||||
|
self.stream
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TcpServer {
|
pub struct TcpServer {
|
||||||
|
@ -40,6 +40,10 @@ impl Stream for TlsStream {
|
|||||||
fn stream(&mut self) -> &mut Self::Socket {
|
fn stream(&mut self) -> &mut Self::Socket {
|
||||||
&mut self.stream
|
&mut self.stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_stream(self) -> Self::Socket {
|
||||||
|
self.stream
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TlsServer {
|
pub struct TlsServer {
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
pub mod color;
|
pub mod color;
|
||||||
|
pub mod string;
|
||||||
|
4
server/src/util/string.rs
Normal file
4
server/src/util/string.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub fn minimize_whitespace(s:&str) -> String
|
||||||
|
{
|
||||||
|
s.lines().map(|line| line.trim()).collect::<String>()
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
import(".wasm");//.then(module=>{module.main();})
|
|
Loading…
x
Reference in New Issue
Block a user