2021-10-12 06:55:25 -04:00
|
|
|
use std::io;
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
use std::rc::Rc;
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2020-12-27 20:10:47 -05:00
|
|
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
2020-04-17 17:38:01 -04:00
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
use tokio::task;
|
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
use mlua::{
|
|
|
|
chunk, AnyUserData, Function, Lua, RegistryKey, String as LuaString, UserData, UserDataMethods,
|
|
|
|
};
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
struct LuaTcpStream(TcpStream);
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
impl UserData for LuaTcpStream {
|
2020-04-17 17:38:01 -04:00
|
|
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
2021-10-12 06:55:25 -04:00
|
|
|
methods.add_method("peer_addr", |_, this, ()| {
|
|
|
|
Ok(this.0.peer_addr()?.to_string())
|
2020-04-17 17:38:01 -04:00
|
|
|
});
|
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
methods.add_async_function(
|
|
|
|
"read",
|
|
|
|
|lua, (this, size): (AnyUserData, usize)| async move {
|
|
|
|
let mut this = this.borrow_mut::<Self>()?;
|
|
|
|
let mut buf = vec![0; size];
|
|
|
|
let n = this.0.read(&mut buf).await?;
|
|
|
|
buf.truncate(n);
|
|
|
|
lua.create_string(&buf)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
methods.add_async_function(
|
|
|
|
"write",
|
|
|
|
|_, (this, data): (AnyUserData, LuaString)| async move {
|
|
|
|
let mut this = this.borrow_mut::<Self>()?;
|
|
|
|
let n = this.0.write(&data.as_bytes()).await?;
|
|
|
|
Ok(n)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
methods.add_async_function("close", |_, this: AnyUserData| async move {
|
|
|
|
let mut this = this.borrow_mut::<Self>()?;
|
|
|
|
this.0.shutdown().await?;
|
|
|
|
Ok(())
|
2020-04-17 17:38:01 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
async fn run_server(lua: Lua, handler: RegistryKey) -> io::Result<()> {
|
|
|
|
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
|
|
|
|
let listener = TcpListener::bind(addr).await.expect("cannot bind addr");
|
|
|
|
|
|
|
|
println!("Listening on {}", addr);
|
|
|
|
|
|
|
|
let lua = Rc::new(lua);
|
|
|
|
let handler = Rc::new(handler);
|
|
|
|
loop {
|
|
|
|
let (stream, _) = match listener.accept().await {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(err) if is_transient_error(&err) => continue,
|
|
|
|
Err(err) => return Err(err),
|
|
|
|
};
|
|
|
|
|
|
|
|
let lua = lua.clone();
|
|
|
|
let handler = handler.clone();
|
|
|
|
task::spawn_local(async move {
|
|
|
|
let handler: Function = lua
|
|
|
|
.registry_value(&handler)
|
|
|
|
.expect("cannot get Lua handler");
|
|
|
|
|
|
|
|
let stream = LuaTcpStream(stream);
|
|
|
|
if let Err(err) = handler.call_async::<_, ()>(stream).await {
|
|
|
|
eprintln!("{}", err);
|
|
|
|
}
|
2020-04-17 17:38:01 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
#[tokio::main(flavor = "current_thread")]
|
|
|
|
async fn main() {
|
|
|
|
let lua = Lua::new();
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
// Create Lua handler function
|
|
|
|
let handler_fn = lua
|
2021-06-19 09:41:48 -04:00
|
|
|
.load(chunk! {
|
2021-10-12 06:55:25 -04:00
|
|
|
function(stream)
|
2020-04-18 20:23:42 -04:00
|
|
|
local peer_addr = stream:peer_addr()
|
|
|
|
print("connected from "..peer_addr)
|
2020-05-05 08:03:28 -04:00
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
while true do
|
|
|
|
local data = stream:read(100)
|
|
|
|
data = data:match("^%s*(.-)%s*$") // trim
|
|
|
|
print("["..peer_addr.."] "..data)
|
|
|
|
if data == "bye" then
|
|
|
|
stream:write("bye bye\n")
|
|
|
|
stream:close()
|
|
|
|
return
|
2020-04-18 20:23:42 -04:00
|
|
|
end
|
2021-10-12 06:55:25 -04:00
|
|
|
stream:write("echo: "..data.."\n")
|
|
|
|
end
|
2020-04-18 20:23:42 -04:00
|
|
|
end
|
2021-06-19 09:41:48 -04:00
|
|
|
})
|
2021-10-12 06:55:25 -04:00
|
|
|
.eval::<Function>()
|
|
|
|
.expect("cannot create Lua handler");
|
|
|
|
|
|
|
|
// Store it in the Registry
|
|
|
|
let handler = lua
|
|
|
|
.create_registry_value(handler_fn)
|
|
|
|
.expect("cannot store Lua handler");
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2020-04-18 20:23:42 -04:00
|
|
|
task::LocalSet::new()
|
2021-10-12 06:55:25 -04:00
|
|
|
.run_until(run_server(lua, handler))
|
2020-04-18 20:23:42 -04:00
|
|
|
.await
|
2021-10-12 06:55:25 -04:00
|
|
|
.expect("cannot run server")
|
2020-04-17 17:38:01 -04:00
|
|
|
}
|
2020-05-05 08:03:28 -04:00
|
|
|
|
2021-10-12 06:55:25 -04:00
|
|
|
fn is_transient_error(e: &io::Error) -> bool {
|
|
|
|
e.kind() == io::ErrorKind::ConnectionRefused
|
|
|
|
|| e.kind() == io::ErrorKind::ConnectionAborted
|
|
|
|
|| e.kind() == io::ErrorKind::ConnectionReset
|
2020-05-05 08:03:28 -04:00
|
|
|
}
|