Skip to content

Commit

Permalink
Merge pull request torvalds#752 from wedsonaf/echo-server
Browse files Browse the repository at this point in the history
samples/rust: add echo server sample
  • Loading branch information
wedsonaf authored Jul 1, 2022
2 parents e1b764a + 7ee240a commit 4536277
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
10 changes: 10 additions & 0 deletions samples/rust/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ config SAMPLE_RUST_NETFILTER

If unsure, say N.

config SAMPLE_RUST_ECHO_SERVER
tristate "Echo server module"
help
This option builds the Rust echo server module sample.

To compile this as a module, choose M here:
the module will be called rust_echo_server.

If unsure, say N.

config SAMPLE_RUST_HOSTPROGS
bool "Host programs"
help
Expand Down
1 change: 1 addition & 0 deletions samples/rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE_C) += rust_semaphore_c.o
obj-$(CONFIG_SAMPLE_RUST_RANDOM) += rust_random.o
obj-$(CONFIG_SAMPLE_RUST_PLATFORM) += rust_platform.o
obj-$(CONFIG_SAMPLE_RUST_NETFILTER) += rust_netfilter.o
obj-$(CONFIG_SAMPLE_RUST_ECHO_SERVER) += rust_echo_server.o

subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs
60 changes: 60 additions & 0 deletions samples/rust/rust_echo_server.rs
Original file line number Diff line number Diff line change
@@ -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::{Ref, RefBorrow},
};

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: Ref<impl Executor>) {
loop {
if let Ok(stream) = listener.accept().await {
let _ = spawn_task!(executor.as_ref_borrow(), echo_server(stream));
}
}
}

fn start_listener(ex: RefBorrow<'_, 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: b"rust_echo_server",
author: b"Rust for Linux Contributors",
description: b"Rust tcp echo sample",
license: b"GPL v2",
}

0 comments on commit 4536277

Please sign in to comment.