summaryrefslogtreecommitdiff
path: root/samples/rust/rust_echo_server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'samples/rust/rust_echo_server.rs')
-rw-r--r--samples/rust/rust_echo_server.rs60
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",
+}