Start setting up new server

This commit is contained in:
Filip Tibell 2024-02-13 17:42:01 +01:00
parent fc60d5b031
commit 718572f537
No known key found for this signature in database
5 changed files with 133 additions and 2 deletions

29
Cargo.lock generated
View file

@ -1164,6 +1164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.0.0",
"http-body 1.0.0",
@ -1171,6 +1172,9 @@ dependencies = [
"pin-project-lite",
"socket2",
"tokio",
"tower",
"tower-service",
"tracing",
]
[[package]]
@ -1356,8 +1360,10 @@ dependencies = [
"env_logger",
"futures-util",
"glam",
"http-body-util",
"hyper 1.1.0",
"hyper-tungstenite",
"hyper-util",
"include_dir",
"itertools",
"lz4_flex",
@ -2805,6 +2811,28 @@ dependencies = [
"winnow",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]]
name = "tower-service"
version = "0.3.2"
@ -2817,6 +2845,7 @@ version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",

View file

@ -109,10 +109,14 @@ toml = { version = "0.8", features = ["preserve_order"] }
### NET
hyper = { version = "1.1", features = ["full"] }
hyper-util = { version = "0.1", features = ["full"] }
http-body-util = { version = "0.1" }
hyper-tungstenite = { version = "0.13" }
reqwest = { version = "0.11", default-features = false, features = [
"rustls-tls",
] }
tokio-tungstenite = { version = "0.21", features = ["rustls-tls-webpki-roots"] }
### DATETIME

View file

@ -167,7 +167,7 @@ impl<'lua> FromLua<'lua> for ServeConfig<'lua> {
Ok(ServeConfig {
handle_request: f.clone(),
handle_web_socket: None,
address: DEFAULT_IP_ADDRESS.clone(),
address: DEFAULT_IP_ADDRESS,
})
} else if let LuaValue::Table(t) = &value {
// Table means custom options

View file

@ -5,6 +5,7 @@ use mlua_luau_scheduler::LuaSpawnExt;
mod client;
mod config;
mod server;
mod util;
mod websocket;
@ -13,6 +14,7 @@ use crate::lune::util::TableBuilder;
use self::{
client::{NetClient, NetClientBuilder},
config::{RequestConfig, ServeConfig},
server::serve,
util::create_user_agent_header,
websocket::NetWebSocket,
};
@ -63,7 +65,7 @@ async fn net_serve<'lua>(
lua: &'lua Lua,
(port, config): (u16, ServeConfig<'lua>),
) -> LuaResult<LuaTable<'lua>> {
unimplemented!()
serve(lua, port, config).await
}
fn net_url_encode<'lua>(

View file

@ -0,0 +1,96 @@
use std::{convert::Infallible, net::SocketAddr};
use http_body_util::Full;
use hyper_util::rt::TokioIo;
use tokio::{net::TcpListener, spawn, sync::mpsc::channel};
use hyper::{
body::{Bytes, Incoming},
server::conn::http1,
service::service_fn,
Request, Response,
};
use mlua::prelude::*;
use crate::lune::util::TableBuilder;
use super::config::ServeConfig;
const SERVER_IMPL_LUA: &str = r#"
spawn(function()
while true do
local id, request, socket, exit = server:next()
if exit then
break
end
spawn(function()
if socket ~= nil then
local handler = server:getRequestHandler()
local response = handler(request)
server:respond(id, response)
elseif request ~= nil then
local handler = server:getWebsocketHandler()
handler(socket)
end
end)
end
end)
"#;
pub(super) async fn serve<'lua>(
lua: &'lua Lua,
port: u16,
config: ServeConfig<'lua>,
) -> LuaResult<LuaTable<'lua>> {
let addr = SocketAddr::from((config.address, port));
let listener = TcpListener::bind(addr).await.map_err(|e| {
LuaError::external(format!(
"Failed to bind to {addr}\n{}",
e.to_string()
.replace("error creating server listener: ", "> ")
))
})?;
// Spawn a new task to accept incoming connections + listening for shutdown
let (shutdown_tx, mut shutdown_rx) = channel::<()>(1);
spawn(async move {
loop {
tokio::select! {
// If we receive a shutdown signal, break the loop
_ = shutdown_rx.recv() => break,
// Each connection gets its own task that forwards to lua
accepted = listener.accept() => {
match accepted {
Err(e) => println!("Error accepting connection: {e}"),
Ok((s, _)) => {
let io = TokioIo::new(s);
spawn(async move {
if let Err(err) = http1::Builder::new()
.serve_connection(io, service_fn(|_| async move {
// TODO: Forward to lua somehow
Ok::<_, Infallible>(Response::new(Full::new(Bytes::from("Hello, World!"))))
}))
.await
{
println!("Error serving connection: {err:?}");
}
});
}
}
}
}
}
});
// Create a new read-only table that contains methods
// for manipulating server behavior and shutting it down
let handle_stop = move |_, _: ()| match shutdown_tx.try_send(()) {
Err(_) => Err(LuaError::runtime("Server has already been stopped")),
Ok(_) => Ok(()),
};
TableBuilder::new(lua)?
.with_function("stop", handle_stop)?
.build_readonly()
}