diff --git a/Cargo.lock b/Cargo.lock index 059c1dc..87d63a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,18 +112,191 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "h2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "hermit-abi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.10" @@ -156,6 +329,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "memchr" version = "2.7.1" @@ -207,6 +386,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "parking_lot" version = "0.12.1" @@ -230,12 +415,38 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.30" @@ -317,10 +528,19 @@ dependencies = [ ] [[package]] -name = "smallvec" -version = "1.11.2" +name = "slab" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -404,6 +624,74 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -416,6 +704,15 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -494,5 +791,8 @@ version = "0.1.0" dependencies = [ "diesel", "dotenvy", + "http-body-util", + "hyper", + "hyper-util", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index bd4bbb0..34c52a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,6 @@ edition = "2021" diesel = { version = "2.1.4", features = ["sqlite"] } dotenvy = "0.15" tokio = {version = "1.36.0", features = ["full"]} +hyper = {version = "1.2.0", features = ["full"]} +hyper-util = { version = "0.1", features = ["full"] } +http-body-util = "0.1" diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..b78ffca --- /dev/null +++ b/src/api.rs @@ -0,0 +1,3 @@ +use std::net::SocketAddr; + +pub async fn api_listener_loop(addr: SocketAddr) {} diff --git a/src/main.rs b/src/main.rs index 2720046..4aff029 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,113 +1,21 @@ -use std::{error::Error, net::SocketAddr, sync::Arc}; +use std::{error::Error, net::SocketAddr}; -use db::{lib::establish_connection, models::Record}; -use errors::DatabaseError; -use parser::FromBytes; -use structs::{Message, Question}; -use tokio::net::UdpSocket; - -use crate::structs::{Class, Type, RR}; +use crate::{api::api_listener_loop, resolver::resolver_listener_loop}; +mod api; mod db; mod errors; mod parser; +mod resolver; mod structs; -mod worker; - -const MAX_DATAGRAM_SIZE: usize = 40_96; - -async fn get_from_database(question: Question) -> Result { - let db_connection = &mut establish_connection(); - let record = Record::get( - db_connection, - question.qname.join("."), - question.qtype as i32, - question.qclass as i32, - ) - .map_err(|e| DatabaseError { - message: e.to_string(), - })?; - - Ok(RR { - name: record.name.split(".").map(str::to_string).collect(), - _type: Type::try_from(record._type as u16).map_err(|e| DatabaseError { message: e })?, - class: Class::try_from(record.class as u16).map_err(|e| DatabaseError { message: e })?, - ttl: record.ttl, - rdlength: record.rdlength as u16, - rdata: record.rdata, - }) -} - -async fn insert_into_database(rr: RR) -> Result<(), DatabaseError> { - let db_connection = &mut establish_connection(); - let record = Record { - name: rr.name.join("."), - _type: rr._type as i32, - class: rr.class as i32, - ttl: rr.ttl, - rdlength: rr.rdlength as i32, - rdata: rr.rdata, - }; - - Record::create(db_connection, record).map_err(|e| DatabaseError { - message: e.to_string(), - })?; - - Ok(()) -} - -async fn create_query(message: Message) -> Message { - let mut response = message.clone(); - - let answer = get_from_database(message.question).await; - - match answer { - Ok(rr) => { - response.header.flags |= 0b1000010110000000; - response.header.ancount = 1; - response.header.arcount = 0; - response.answer = Some(rr) - } - Err(e) => { - response.header.flags |= 0b1000010110000011; - eprintln!("{}", e); - } - } - - response -} #[tokio::main] async fn main() -> Result<(), Box> { - // insert_into_database(RR{ - // name: vec![String::from("example"),String::from("org")], - // _type: Type::A, - // class: Class::IN, - // ttl: 100, - // rdlength: 4, - // rdata: vec![1,2,3,4] - // }).await; - // - // return Ok(()); - - let local_addr: SocketAddr = "127.0.0.1:8080".parse()?; - - let socket_shared = Arc::new(UdpSocket::bind(local_addr).await?); - - loop { - let mut data = vec![0u8; MAX_DATAGRAM_SIZE]; - let (len, addr) = socket_shared.recv_from(&mut data).await?; - match Message::from_bytes(&data[..len]) { - Ok(message) => { - let socket = socket_shared.clone(); - tokio::spawn(async move { - let response = create_query(message).await; - let _ = socket - .send_to(Message::to_bytes(response).as_slice(), addr) - .await; - }); - } - Err(err) => println!("{}", err), - }; - } + let api_addr = SocketAddr::from(([127, 0, 0, 1], 3000)); + let resolver_add = SocketAddr::from(([127, 0, 0, 1], 8080)); + let (_, _) = tokio::join!( + resolver_listener_loop(resolver_add), + api_listener_loop(api_addr) + ); + Ok(()) } diff --git a/src/parser.rs b/src/parser.rs index 9180519..9c92d4a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -8,23 +8,23 @@ use crate::{ type Result = std::result::Result; impl TryFrom for Type { - type Error = String; + type Error = String; fn try_from(value: u16) -> std::result::Result { match value { x if x == Type::A as u16 => Ok(Type::A), - _ => Err(format!("Invalid Type value: {}",value)), + _ => Err(format!("Invalid Type value: {}", value)), } } } impl TryFrom for Class { - type Error = String; + type Error = String; fn try_from(value: u16) -> std::result::Result { match value { x if x == Class::IN as u16 => Ok(Class::IN), - _ => Err(format!("Invalid Class value: {}",value)), + _ => Err(format!("Invalid Class value: {}", value)), } } } diff --git a/src/queue.rs b/src/queue.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/resolver.rs b/src/resolver.rs index e69de29..2a8e94c 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -0,0 +1,94 @@ +use std::error::Error; +use std::net::SocketAddr; +use std::sync::Arc; + +use tokio::net::UdpSocket; + +use crate::db::{lib::establish_connection, models::Record}; +use crate::errors::DatabaseError; +use crate::parser::FromBytes; +use crate::structs::{Message, Question}; + +use crate::structs::{Class, Type, RR}; +const MAX_DATAGRAM_SIZE: usize = 40_96; + +async fn get_from_database(question: Question) -> Result { + let db_connection = &mut establish_connection(); + let record = Record::get( + db_connection, + question.qname.join("."), + question.qtype as i32, + question.qclass as i32, + ) + .map_err(|e| DatabaseError { + message: e.to_string(), + })?; + + Ok(RR { + name: record.name.split(".").map(str::to_string).collect(), + _type: Type::try_from(record._type as u16).map_err(|e| DatabaseError { message: e })?, + class: Class::try_from(record.class as u16).map_err(|e| DatabaseError { message: e })?, + ttl: record.ttl, + rdlength: record.rdlength as u16, + rdata: record.rdata, + }) +} + +async fn insert_into_database(rr: RR) -> Result<(), DatabaseError> { + let db_connection = &mut establish_connection(); + let record = Record { + name: rr.name.join("."), + _type: rr._type as i32, + class: rr.class as i32, + ttl: rr.ttl, + rdlength: rr.rdlength as i32, + rdata: rr.rdata, + }; + + Record::create(db_connection, record).map_err(|e| DatabaseError { + message: e.to_string(), + })?; + + Ok(()) +} + +async fn create_query(message: Message) -> Message { + let mut response = message.clone(); + + let answer = get_from_database(message.question).await; + + match answer { + Ok(rr) => { + response.header.flags |= 0b1000010110000000; + response.header.ancount = 1; + response.header.arcount = 0; + response.answer = Some(rr) + } + Err(e) => { + response.header.flags |= 0b1000010110000011; + eprintln!("{}", e); + } + } + + response +} + +pub async fn resolver_listener_loop(addr: SocketAddr) -> Result<(), Box> { + let socket_shared = Arc::new(UdpSocket::bind(addr).await?); + loop { + let mut data = vec![0u8; MAX_DATAGRAM_SIZE]; + let (len, addr) = socket_shared.recv_from(&mut data).await?; + match Message::from_bytes(&data[..len]) { + Ok(message) => { + let socket = socket_shared.clone(); + tokio::spawn(async move { + let response = create_query(message).await; + let _ = socket + .send_to(Message::to_bytes(response).as_slice(), addr) + .await; + }); + } + Err(err) => println!("{}", err), + }; + } +} diff --git a/src/schema.rs b/src/schema.rs deleted file mode 100644 index 4d63d37..0000000 --- a/src/schema.rs +++ /dev/null @@ -1,13 +0,0 @@ -// @generated automatically by Diesel CLI. - -diesel::table! { - records (name, type_, class) { - name -> Text, - #[sql_name = "type"] - type_ -> Integer, - class -> Integer, - ttl -> Integer, - rdlength -> Integer, - rdata -> Binary, - } -} diff --git a/src/worker.rs b/src/worker.rs deleted file mode 100644 index aa52965..0000000 --- a/src/worker.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::collections::VecDeque; - -use crate::Message; - -struct Worker { - queue: VecDeque -} - -impl Worker { - pub fn new() -> Worker { - Worker { queue: VecDeque::new() } - } - - pub fn append() { - - } -} - -