Skip to content

Commit 0a03363

Browse files
committed
feat: add backbone of wasm
1 parent e04254e commit 0a03363

File tree

14 files changed

+112
-24
lines changed

14 files changed

+112
-24
lines changed

Cargo.toml

+8-3
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ moka = { version = "0.12", features = ["future", "sync"] }
5454
url = "2.5"
5555
regex = "1.10"
5656
hex = "0.4"
57-
strum = { version = "0.26", default-features = false, features = ["strum_macros", "derive"] }
58-
strum_macros = "0.26"
57+
strum = { version = "0.27", default-features = false, features = ["strum_macros", "derive"] }
58+
strum_macros = "0.27"
5959
deadpool = "0.12"
6060
socket2 = "0.5"
6161
mlua = { version = "0.10", features = ["luajit", "vendored", "serialize", "async", "macros", "send", "anyhow"] }
@@ -66,11 +66,16 @@ tokio-rustls = "0.26"
6666
httparse = "1.9"
6767
http = "1.2"
6868
string_cache = "0.8"
69-
rand = "0.8"
69+
rand = "0.9"
7070
resolv-conf = "0.7"
7171
bitflags = "2.6"
7272
sha2 = "0.10"
7373

74+
wasmedge-sdk = "0.13.2"
75+
wasmedge-sys = "0.17.5"
76+
wasmedge-types = "0.4.4"
77+
wasmedge-macro = "0.6.1"
78+
7479
[dev-dependencies]
7580
hex = "0.4"
7681
pretty_env_logger = "0.5"

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
# ZeroDNS
44

5-
t![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/jjeffcaii/zerodns/rust.yml)
5+
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/jjeffcaii/zerodns/rust.yml)
66
[![Codecov](https://img.shields.io/codecov/c/github/jjeffcaii/zerodns)](https://app.codecov.io/gh/jjeffcaii/zerodns)
77
[![Crates.io Version](https://img.shields.io/crates/v/zerodns)](https://crates.io/crates/zerodns)
88
[![Crates.io Total Downloads](https://img.shields.io/crates/d/zerodns)](https://crates.io/crates/zerodns)
99
![GitHub Tag](https://img.shields.io/github/v/tag/jjeffcaii/zerodns)
1010
![GitHub License](https://img.shields.io/github/license/jjeffcaii/zerodns)
1111

12-
a DNS server in Rust, which is inspired from chinadns/dnsmasq.
12+
a flexible DNS server in Rust, which is inspired from chinadns/dnsmasq.
1313

1414
> :construction_worker: WARNING: still in an active development!!!
1515

justfile

100755100644
File mode changed.

src/client/lookup.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{Error, Result};
66
use hashbrown::HashMap;
77
use moka::future::Cache;
88
use once_cell::sync::Lazy;
9+
use rand::Rng;
910
use smallvec::SmallVec;
1011
use std::net::Ipv4Addr;
1112
use std::time::Duration;
@@ -70,12 +71,7 @@ impl LookupCache {
7071
.opcode(OpCode::StandardQuery)
7172
.build();
7273

73-
let id = {
74-
use rand::prelude::*;
75-
76-
let mut rng = thread_rng();
77-
rng.gen_range(1..u16::MAX)
78-
};
74+
let id = rand::rng().random_range(1..u16::MAX);
7975

8076
let req0 = Message::builder()
8177
.id(id)

src/client/udp.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use futures::StreamExt;
22
use hashbrown::HashMap;
33
use once_cell::sync::Lazy;
4-
use rand::{thread_rng, Rng};
54
use socket2::{Domain, Protocol, Type};
65
use std::fmt::{Display, Formatter};
76
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
@@ -202,8 +201,8 @@ impl MultiplexUdpClient {
202201
});
203202

204203
let seq = {
205-
let mut rng = thread_rng();
206-
rng.gen_range(1..u16::MAX)
204+
use rand::prelude::*;
205+
rand::rng().random_range(1..u16::MAX)
207206
};
208207

209208
Self {

src/cmds/resolve.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,8 @@ pub(crate) async fn execute(sm: &ArgMatches) -> Result<()> {
7272
let req = {
7373
let mut bu = Message::builder()
7474
.id({
75-
use rand::Rng;
76-
let mut rng = rand::thread_rng();
77-
rng.gen_range(1024..u16::MAX)
75+
use rand::prelude::*;
76+
rand::rng().random_range(1024..u16::MAX)
7877
})
7978
.flags(flags);
8079

src/filter/lua.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,15 @@ struct LuaContext(*mut Context, *mut Message, *mut Option<Message>);
323323

324324
impl UserData for LuaContext {
325325
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
326-
fields.add_field_method_get("request", |lua, this| {
326+
fields.add_field_method_get("request", |_lua, this| {
327327
let msg = LuaMessage(Clone::clone(unsafe { this.1.as_ref().unwrap() }));
328328
Ok(msg)
329329
});
330+
331+
fields.add_field_method_get("peer", |_lua, this| {
332+
let ctx = unsafe { this.0.as_ref().unwrap() };
333+
Ok(ctx.client_addr().to_string())
334+
});
330335
}
331336

332337
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {

src/filter/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ mod noop;
2020
mod proto;
2121
mod proxyby;
2222
mod registry;
23+
mod wasm;

src/filter/proto.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::protocol::Message;
22
use crate::Result;
3+
use std::net::SocketAddr;
34

45
#[derive(Debug, Copy, Clone, Default, Hash, PartialEq, Eq)]
56
pub struct ContextFlags(u64);
@@ -13,6 +14,13 @@ bitflags! {
1314
#[derive(Debug, Default)]
1415
pub struct Context {
1516
pub flags: ContextFlags,
17+
pub(crate) peer: Option<SocketAddr>,
18+
}
19+
20+
impl Context {
21+
pub fn client_addr(&self) -> SocketAddr {
22+
self.peer.unwrap()
23+
}
1624
}
1725

1826
#[async_trait::async_trait]

src/filter/wasm.rs

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use super::{Context, Filter, FilterFactory, Options};
2+
use crate::protocol::Message;
3+
use crate::Result;
4+
use async_trait::async_trait;
5+
use std::result::Result as StdResult;
6+
use wasmedge_sdk::{params, Module, Store, VmBuilder, WasmVal};
7+
8+
struct WasmFilter {
9+
next: Option<Box<dyn Filter>>,
10+
module: Module,
11+
}
12+
13+
#[async_trait]
14+
impl Filter for WasmFilter {
15+
async fn handle(
16+
&self,
17+
ctx: &mut Context,
18+
req: &mut Message,
19+
res: &mut Option<Message>,
20+
) -> Result<()> {
21+
let vm = {
22+
let store = Store::new()?;
23+
let vm = VmBuilder::new().with_store(store).build()?;
24+
vm.register_module(Some("extern"), Clone::clone(&self.module))?
25+
};
26+
27+
let res = vm.run_func(Some("extern"), "add", params!(1_i32, 2_i32))?;
28+
29+
todo!()
30+
}
31+
32+
fn set_next(&mut self, next: Box<dyn Filter>) {
33+
self.next.replace(next);
34+
}
35+
}
36+
37+
struct WasmFilterFactory {
38+
module: Module,
39+
}
40+
41+
impl FilterFactory for WasmFilterFactory {
42+
type Item = WasmFilter;
43+
44+
fn get(&self) -> Result<Self::Item> {
45+
Ok(WasmFilter {
46+
next: None,
47+
module: Clone::clone(&self.module),
48+
})
49+
}
50+
}
51+
52+
impl TryFrom<&Options> for WasmFilterFactory {
53+
type Error = anyhow::Error;
54+
55+
fn try_from(value: &Options) -> StdResult<Self, Self::Error> {
56+
let path = value
57+
.get("path")
58+
.ok_or_else(|| anyhow!("the property of 'path' is required"))?
59+
.as_str()
60+
.ok_or_else(|| anyhow!("invalid 'path' format"))?;
61+
62+
let module = Module::from_file(None, path)?;
63+
64+
Ok(Self { module })
65+
}
66+
}

src/handler/filtered.rs

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ mod tests {
123123
.unwrap();
124124

125125
let mut ctx = Context::default();
126+
126127
let res = h.handle(&mut ctx, &mut req).await;
127128
assert!(res.is_ok_and(|it| it.is_none()));
128129
}

src/server/helper.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::filter::Context;
44
use crate::handler::Handler;
55
use crate::protocol::{Flags, Message, RCode};
66
use crate::{Error as ZError, Result};
7+
use std::net::SocketAddr;
78
use std::sync::atomic::{AtomicBool, Ordering};
89
use std::sync::Arc;
910

@@ -85,18 +86,25 @@ fn convert_error_to_message(
8586
}
8687

8788
#[inline]
88-
async fn handle_<H>(req: &Message, h: Arc<H>) -> Result<Message>
89+
async fn handle_<H>(peer: SocketAddr, req: &Message, h: Arc<H>) -> Result<Message>
8990
where
9091
H: Handler,
9192
{
9293
let mut req = Clone::clone(req);
9394
let mut ctx = Context::default();
95+
ctx.peer.replace(peer);
96+
9497
h.handle(&mut ctx, &mut req)
9598
.await?
9699
.ok_or_else(|| anyhow!(ZError::ResolveNothing))
97100
}
98101

99-
pub(super) async fn handle<H, C>(req: Message, h: Arc<H>, cache: Option<Arc<C>>) -> (Message, bool)
102+
pub(super) async fn handle<H, C>(
103+
peer: SocketAddr,
104+
req: Message,
105+
h: Arc<H>,
106+
cache: Option<Arc<C>>,
107+
) -> (Message, bool)
100108
where
101109
H: Handler,
102110
C: LoadingCache,
@@ -106,7 +114,7 @@ where
106114
}
107115

108116
let (res, cached) = match cache.as_deref() {
109-
None => (handle_(&req, h).await, false),
117+
None => (handle_(peer, &req, h).await, false),
110118
Some(lc) => {
111119
let cached = Arc::new(AtomicBool::new(true));
112120

@@ -115,7 +123,7 @@ where
115123
let cached = Clone::clone(&cached);
116124
lc.try_get_with_fixed(req, move |req| {
117125
cached.store(false, Ordering::SeqCst);
118-
async move { handle_(&req, h).await }
126+
async move { handle_(peer, &req, h).await }
119127
})
120128
.await
121129
};

src/server/tcp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ where
9090
let req = next?;
9191
let handler = Clone::clone(&handler);
9292
let cache = Clone::clone(&cache);
93-
let (res, cached) = super::helper::handle(req, handler, cache).await;
93+
let (res, cached) = super::helper::handle(addr, req, handler, cache).await;
9494

9595
if res.answer_count() > 0 {
9696
for next in res.answers() {

src/server/udp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ where
4141
h: Arc<H>,
4242
cache: Option<Arc<C>>,
4343
) {
44-
let (res, cached) = helper::handle(req, h, cache).await;
44+
let (res, cached) = helper::handle(peer, req, h, cache).await;
4545

4646
if res.answer_count() > 0 {
4747
for next in res.answers() {

0 commit comments

Comments
 (0)