Skip to content

Commit 7ee240a

Browse files
committed
samples/rust: add echo server sample
This example uses Rust async for the server and a workqueue-based executor to run async tasks. Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
1 parent 53bbccb commit 7ee240a

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

samples/rust/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,16 @@ config SAMPLE_RUST_NETFILTER
130130

131131
If unsure, say N.
132132

133+
config SAMPLE_RUST_ECHO_SERVER
134+
tristate "Echo server module"
135+
help
136+
This option builds the Rust echo server module sample.
137+
138+
To compile this as a module, choose M here:
139+
the module will be called rust_echo_server.
140+
141+
If unsure, say N.
142+
133143
config SAMPLE_RUST_HOSTPROGS
134144
bool "Host programs"
135145
help

samples/rust/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE_C) += rust_semaphore_c.o
1212
obj-$(CONFIG_SAMPLE_RUST_RANDOM) += rust_random.o
1313
obj-$(CONFIG_SAMPLE_RUST_PLATFORM) += rust_platform.o
1414
obj-$(CONFIG_SAMPLE_RUST_NETFILTER) += rust_netfilter.o
15+
obj-$(CONFIG_SAMPLE_RUST_ECHO_SERVER) += rust_echo_server.o
1516

1617
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs

samples/rust/rust_echo_server.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Rust echo server sample.
4+
5+
use kernel::{
6+
kasync::executor::{workqueue::Executor as WqExecutor, AutoStopHandle, Executor},
7+
kasync::net::{TcpListener, TcpStream},
8+
net::{self, Ipv4Addr, SocketAddr, SocketAddrV4},
9+
prelude::*,
10+
spawn_task,
11+
sync::{Ref, RefBorrow},
12+
};
13+
14+
async fn echo_server(stream: TcpStream) -> Result {
15+
let mut buf = [0u8; 1024];
16+
loop {
17+
let n = stream.read(&mut buf).await?;
18+
if n == 0 {
19+
return Ok(());
20+
}
21+
stream.write_all(&buf[..n]).await?;
22+
}
23+
}
24+
25+
async fn accept_loop(listener: TcpListener, executor: Ref<impl Executor>) {
26+
loop {
27+
if let Ok(stream) = listener.accept().await {
28+
let _ = spawn_task!(executor.as_ref_borrow(), echo_server(stream));
29+
}
30+
}
31+
}
32+
33+
fn start_listener(ex: RefBorrow<'_, impl Executor + Send + Sync + 'static>) -> Result {
34+
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::ANY, 8080));
35+
let listener = TcpListener::try_new(net::init_ns(), &addr)?;
36+
spawn_task!(ex, accept_loop(listener, ex.into()))?;
37+
Ok(())
38+
}
39+
40+
struct RustEchoServer {
41+
_handle: AutoStopHandle<dyn Executor>,
42+
}
43+
44+
impl kernel::Module for RustEchoServer {
45+
fn init(_name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
46+
let handle = WqExecutor::try_new(kernel::workqueue::system())?;
47+
start_listener(handle.executor())?;
48+
Ok(Self {
49+
_handle: handle.into(),
50+
})
51+
}
52+
}
53+
54+
module! {
55+
type: RustEchoServer,
56+
name: b"rust_echo_server",
57+
author: b"Rust for Linux Contributors",
58+
description: b"Rust tcp echo sample",
59+
license: b"GPL v2",
60+
}

0 commit comments

Comments
 (0)