diff options
Diffstat (limited to 'samples/rust/rust_echo_server.rs')
-rw-r--r-- | samples/rust/rust_echo_server.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/samples/rust/rust_echo_server.rs b/samples/rust/rust_echo_server.rs new file mode 100644 index 000000000000..e57f3dd9cd64 --- /dev/null +++ b/samples/rust/rust_echo_server.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust echo server sample. + +use kernel::{ + kasync::executor::{workqueue::Executor as WqExecutor, AutoStopHandle, Executor}, + kasync::net::{TcpListener, TcpStream}, + net::{self, Ipv4Addr, SocketAddr, SocketAddrV4}, + prelude::*, + spawn_task, + sync::{Arc, ArcBorrow}, +}; + +async fn echo_server(stream: TcpStream) -> Result { + let mut buf = [0u8; 1024]; + loop { + let n = stream.read(&mut buf).await?; + if n == 0 { + return Ok(()); + } + stream.write_all(&buf[..n]).await?; + } +} + +async fn accept_loop(listener: TcpListener, executor: Arc<impl Executor>) { + loop { + if let Ok(stream) = listener.accept().await { + let _ = spawn_task!(executor.as_arc_borrow(), echo_server(stream)); + } + } +} + +fn start_listener(ex: ArcBorrow<'_, impl Executor + Send + Sync + 'static>) -> Result { + let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::ANY, 8080)); + let listener = TcpListener::try_new(net::init_ns(), &addr)?; + spawn_task!(ex, accept_loop(listener, ex.into()))?; + Ok(()) +} + +struct RustEchoServer { + _handle: AutoStopHandle<dyn Executor>, +} + +impl kernel::Module for RustEchoServer { + fn init(_name: &'static CStr, _module: &'static ThisModule) -> Result<Self> { + let handle = WqExecutor::try_new(kernel::workqueue::system())?; + start_listener(handle.executor())?; + Ok(Self { + _handle: handle.into(), + }) + } +} + +module! { + type: RustEchoServer, + name: "rust_echo_server", + author: "Rust for Linux Contributors", + description: "Rust tcp echo sample", + license: "GPL v2", +} |