refactor to async tokio with modular architecture
- Replace synchronous std::net::UdpSocket with tokio async runtime - Spawn concurrent task per incoming DNS query via tokio::spawn - Extract monolithic main.rs into modules: buffer, header, question, record, packet, config, cache, forward, stats - Share state across tasks via Arc<ServerCtx> with scoped Mutex locks - Add TOML config loading, TTL-aware cache, structured logging, stats - Add CLAUDE.md, README, dns_fun.toml config, and design docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
133
src/header.rs
Normal file
133
src/header.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
use crate::buffer::BytePacketBuffer;
|
||||
use crate::Result;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ResultCode {
|
||||
NOERROR = 0,
|
||||
FORMERR = 1,
|
||||
SERVFAIL = 2,
|
||||
NXDOMAIN = 3,
|
||||
NOTIMP = 4,
|
||||
REFUSED = 5,
|
||||
}
|
||||
|
||||
impl ResultCode {
|
||||
pub fn from_num(num: u8) -> ResultCode {
|
||||
match num {
|
||||
1 => ResultCode::FORMERR,
|
||||
2 => ResultCode::SERVFAIL,
|
||||
3 => ResultCode::NXDOMAIN,
|
||||
4 => ResultCode::NOTIMP,
|
||||
5 => ResultCode::REFUSED,
|
||||
0 | _ => ResultCode::NOERROR,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
ResultCode::NOERROR => "NOERROR",
|
||||
ResultCode::FORMERR => "FORMERR",
|
||||
ResultCode::SERVFAIL => "SERVFAIL",
|
||||
ResultCode::NXDOMAIN => "NXDOMAIN",
|
||||
ResultCode::NOTIMP => "NOTIMP",
|
||||
ResultCode::REFUSED => "REFUSED",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DnsHeader {
|
||||
pub id: u16,
|
||||
|
||||
pub recursion_desired: bool,
|
||||
pub truncated_message: bool,
|
||||
pub authoritative_answer: bool,
|
||||
pub opcode: u8,
|
||||
pub response: bool,
|
||||
|
||||
pub rescode: ResultCode,
|
||||
pub checking_disabled: bool,
|
||||
pub authed_data: bool,
|
||||
pub z: bool,
|
||||
pub recursion_available: bool,
|
||||
|
||||
pub questions: u16,
|
||||
pub answers: u16,
|
||||
pub authoritative_entries: u16,
|
||||
pub resource_entries: u16,
|
||||
}
|
||||
|
||||
impl DnsHeader {
|
||||
pub fn new() -> DnsHeader {
|
||||
DnsHeader {
|
||||
id: 0,
|
||||
recursion_desired: false,
|
||||
truncated_message: false,
|
||||
authoritative_answer: false,
|
||||
opcode: 0,
|
||||
response: false,
|
||||
rescode: ResultCode::NOERROR,
|
||||
checking_disabled: false,
|
||||
authed_data: false,
|
||||
z: false,
|
||||
recursion_available: false,
|
||||
questions: 0,
|
||||
answers: 0,
|
||||
authoritative_entries: 0,
|
||||
resource_entries: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, buffer: &mut BytePacketBuffer) -> Result<()> {
|
||||
self.id = buffer.read_u16()?;
|
||||
|
||||
let flags = buffer.read_u16()?;
|
||||
let a = (flags >> 8) as u8;
|
||||
let b = (flags & 0xFF) as u8;
|
||||
self.recursion_desired = (a & (1 << 0)) > 0;
|
||||
self.truncated_message = (a & (1 << 1)) > 0;
|
||||
self.authoritative_answer = (a & (1 << 2)) > 0;
|
||||
self.opcode = (a >> 3) & 0x0F;
|
||||
self.response = (a & (1 << 7)) > 0;
|
||||
|
||||
self.rescode = ResultCode::from_num(b & 0x0F);
|
||||
self.checking_disabled = (b & (1 << 4)) > 0;
|
||||
self.authed_data = (b & (1 << 5)) > 0;
|
||||
self.z = (b & (1 << 6)) > 0;
|
||||
self.recursion_available = (b & (1 << 7)) > 0;
|
||||
|
||||
self.questions = buffer.read_u16()?;
|
||||
self.answers = buffer.read_u16()?;
|
||||
self.authoritative_entries = buffer.read_u16()?;
|
||||
self.resource_entries = buffer.read_u16()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write(&self, buffer: &mut BytePacketBuffer) -> Result<()> {
|
||||
buffer.write_u16(self.id)?;
|
||||
|
||||
buffer.write_u8(
|
||||
(self.recursion_desired as u8)
|
||||
| ((self.truncated_message as u8) << 1)
|
||||
| ((self.authoritative_answer as u8) << 2)
|
||||
| (self.opcode << 3)
|
||||
| ((self.response as u8) << 7) as u8,
|
||||
)?;
|
||||
|
||||
buffer.write_u8(
|
||||
(self.rescode as u8)
|
||||
| ((self.checking_disabled as u8) << 4)
|
||||
| ((self.authed_data as u8) << 5)
|
||||
| ((self.z as u8) << 6)
|
||||
| ((self.recursion_available as u8) << 7),
|
||||
)?;
|
||||
|
||||
buffer.write_u16(self.questions)?;
|
||||
buffer.write_u16(self.answers)?;
|
||||
buffer.write_u16(self.authoritative_entries)?;
|
||||
buffer.write_u16(self.resource_entries)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user