diff --git a/src/message/type_qtype.rs b/src/message/type_qtype.rs index ccaaf533..dbad368b 100644 --- a/src/message/type_qtype.rs +++ b/src/message/type_qtype.rs @@ -1,4 +1,4 @@ -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug,Copy)] /// Enum For the Type of a RR in a DnsMessage with an Rdata implementation pub enum Qtype { A, diff --git a/src/resolver/async_resolver.rs b/src/resolver/async_resolver.rs index 733e8e33..d7b1da99 100644 --- a/src/resolver/async_resolver.rs +++ b/src/resolver/async_resolver.rs @@ -4,11 +4,11 @@ use crate::client::client_error::ClientError; use crate::dns_cache::DnsCache; use crate::domain_name::DomainName; use crate::message::DnsMessage; -use crate::resolver::{config::ResolverConfig,lookup::LookupIpFutureStub}; +use crate::resolver::{config::ResolverConfig,lookup::LookupFutureStub}; use crate::message::rdata::Rdata; use crate::client::client_connection::ConnectionProtocol; use crate::resolver::resolver_error::ResolverError; - +use crate:: message::type_qtype::Qtype; /// Asynchronous resolver for DNS queries. /// /// This struct contains a cache and a configuration for the resolver. @@ -67,7 +67,7 @@ impl AsyncResolver { let transport_protocol_struct = ConnectionProtocol::from(transport_protocol); self.config.set_protocol(transport_protocol_struct); - let response = self.inner_lookup(domain_name_struct).await; + let response = self.inner_lookup(domain_name_struct,Qtype::A).await; return self.parse_response(response); // match response { @@ -121,11 +121,12 @@ impl AsyncResolver { /// let response = resolver.inner_lookup(domain_name).await; /// assert!(response.is_ok()); /// ``` - async fn inner_lookup(&self, domain_name: DomainName) -> Result { + async fn inner_lookup(&self, domain_name: DomainName,qtype:Qtype) -> Result { // Async query - let response = LookupIpFutureStub::lookup( + let response = LookupFutureStub::lookup( domain_name, + qtype, self.config.clone(), self.cache.clone()) .await; @@ -147,8 +148,28 @@ impl AsyncResolver { /// /// General lookup function /// - pub async fn lookup() { - unimplemented!() + pub async fn lookup(&mut self, domain_name: &str, transport_protocol: &str, qtype:&str ) -> Result{ + println!("[LOOKUP ASYNCRESOLVER]"); + + let domain_name_struct = DomainName::new_from_string(domain_name.to_string()); + let qtype_struct = Qtype::from_str_to_qtype(qtype); + let transport_protocol_struct = ConnectionProtocol::from(transport_protocol); + self.config.set_protocol(transport_protocol_struct); + + let response = self.inner_lookup(domain_name_struct,qtype_struct).await; + + //TODO: parse header and personalised error type + match response { + Ok(val) => { + let rdata = val.get_answer()[0].get_rdata(); + + match rdata { + Rdata::SomeARdata(ip) => Ok(ip.get_address()), // Supongo que A es el tipo correcto + _ => Err(ResolverError::Message("Error Response"))?, + } + } + Err(_) => Err(ResolverError::Message("Error Response"))?, + } } } @@ -158,10 +179,11 @@ impl AsyncResolver { #[cfg(test)] mod async_resolver_test { use crate::client::config::TIMEOUT; - use crate::domain_name::DomainName; + use crate:: message::type_qtype::Qtype; use crate::resolver::config::ResolverConfig; use super::AsyncResolver; use std::time::Duration; + use crate::domain_name::DomainName; #[test] fn create_async_resolver() { @@ -171,45 +193,29 @@ mod async_resolver_test { assert_eq!(resolver.config.get_timeout(), Duration::from_secs(TIMEOUT)); } - //TODO: test inner_lookup #[tokio::test] async fn inner_lookup() { // Create a new resolver with default values let resolver = AsyncResolver::new(ResolverConfig::default()); let domain_name = DomainName::new_from_string("example.com".to_string()); - let response = resolver.inner_lookup(domain_name).await; - assert!(response.is_ok()); - } - - #[ignore] - #[tokio::test] //TODO - async fn lookup_ip() { - - let mut resolver = AsyncResolver::new(ResolverConfig::default()); - - //let runtime = Runtime::new().unwrap(); - let response = resolver.lookup_ip("example.com", "UDP"); - - println!("[TEST FINISH=> {}]",response.await.unwrap()); - // TODO: add assert test Ip example.com + let qtype = Qtype::A; + let response = resolver.inner_lookup(domain_name,qtype).await; - //let response = runtime.block_on(resolver.lookup_ip("niclabs.cl","TCP")); - - // TODO: add assert test ip niclabs.cl - - } - - #[ignore] - #[tokio::test] //TODO - async fn lookupip_example() { - println!("[TEST INIT]"); + //FIXME: add assert + assert!(response.is_ok()); + } - let mut resolver = AsyncResolver::new(ResolverConfig::default()); - - let response = resolver.lookup_ip("example.com", "UDP").await.unwrap(); + #[tokio::test] + async fn inner_lookup_ns() { + // Create a new resolver with default values + let resolver = AsyncResolver::new(ResolverConfig::default()); + let domain_name = DomainName::new_from_string("example.com".to_string()); + let qtype = Qtype::NS; + let response = resolver.inner_lookup(domain_name,qtype).await; + assert!(response.is_ok()); - println!("[TEST FINISH=> {}]",response); - + //FIXME: add assert + println!("Response: {:?}",response); } #[ignore] @@ -225,6 +231,20 @@ mod async_resolver_test { assert!(!ip_address.is_unspecified()); } + #[ignore] + #[tokio::test] + async fn lookup_ns() { + let mut resolver = AsyncResolver::new(ResolverConfig::default()); + let domain_name = "example.com"; + let transport_protocol = "UDP"; + let qtype = "NS"; + let response = resolver.lookup(domain_name, transport_protocol,qtype).await.unwrap(); + + println!("RESPONSE : {}",response); + } + + + // async fn reverse_query() { // let resolver = AsyncResolver::new(ResolverConfig::default()); // let ip_address = "192.168.0.1"; @@ -284,4 +304,8 @@ mod async_resolver_test { //TODO: diferent types of errors //TODO: bad domain name written + + //TODO: prbar diferentes qtype + + } \ No newline at end of file diff --git a/src/resolver/lookup.rs b/src/resolver/lookup.rs index f02424a2..bd1f9e0c 100644 --- a/src/resolver/lookup.rs +++ b/src/resolver/lookup.rs @@ -23,9 +23,11 @@ use crate::client::tcp_connection::ClientTCPConnection; /// /// This implementation of `Future` is used to send a single query to a DNS server. /// When this future is polled by `AsyncResolver`, -pub struct LookupIpFutureStub { +pub struct LookupFutureStub { /// Domain Name associated with the query. name: DomainName, + /// Qtype of search query + record_type: Qtype, /// Resolver configuration. config: ResolverConfig, /// Future that contains the response of the query. @@ -39,7 +41,7 @@ pub struct LookupIpFutureStub { waker: Option, } -impl Future for LookupIpFutureStub { +impl Future for LookupFutureStub { type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -57,6 +59,7 @@ impl Future for LookupIpFutureStub { tokio::spawn( lookup_stub( self.name.clone(), + self.record_type, self.cache.clone(), self.config.get_name_servers(), self.waker.clone(), @@ -72,7 +75,7 @@ impl Future for LookupIpFutureStub { } } -impl LookupIpFutureStub { +impl LookupFutureStub { /// Creates a new `LookupIpFutureStub` with the given configuration. /// @@ -81,12 +84,14 @@ impl LookupIpFutureStub { /// `LookupIpFutureStub` is polled. pub fn lookup( name: DomainName, + qtype: Qtype, config: ResolverConfig, cache: DnsCache ) -> Self { Self { name: name, + record_type: qtype, config: config, query_answer: Arc::new(Mutex::new(future::err(ResolverError::EmptyQuery).boxed())), //FIXME: cambiar a otro tipo el error/inicio @@ -98,6 +103,7 @@ impl LookupIpFutureStub { } pub async fn lookup_stub( //FIXME: podemos ponerle de nombre lookup_strategy y que se le pase ahi un parametro strategy que diga si son los pasos o si funciona como stub name: DomainName, + record_type: Qtype, mut cache: DnsCache, name_servers: Vec<(ClientUDPConnection, ClientTCPConnection)>, waker: Option, @@ -114,7 +120,7 @@ pub async fn lookup_stub( //FIXME: podemos ponerle de nombre lookup_strategy y // Create query let mut new_query = DnsMessage::new_query_message( name.clone(), - Qtype::A, + record_type, Qclass::IN, 0, false, @@ -191,9 +197,8 @@ mod async_resolver_test { use crate::message::rdata::a_rdata::ARdata; use crate::message::rdata::Rdata; use crate::{ domain_name::DomainName, dns_cache::DnsCache}; - use super::lookup_stub; - use tokio::time::Duration; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::time::Duration; use super::*; #[test] @@ -210,8 +215,11 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(a_rdata); cache.add(domain_name_cache, resource_record); - let lookup_future = LookupIpFutureStub::lookup( + let record_type = Qtype::A; + + let lookup_future = LookupFutureStub::lookup( domain_name, + record_type, config, cache ); @@ -231,6 +239,7 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let timeout = Duration::from_secs(2); + let record_type = Qtype::A; let mut config: ResolverConfig = ResolverConfig::default(); let non_existent_server:IpAddr = IpAddr::V4(Ipv4Addr::new(44, 44, 1, 81)); @@ -241,7 +250,7 @@ mod async_resolver_test { config.set_retry(1); let cache = DnsCache::new(); - let response_future = LookupIpFutureStub::lookup(domain_name, config, cache).await; + let response_future = LookupFutureStub::lookup(domain_name, record_type ,config, cache).await; println!("response_future {:?}",response_future); assert_eq!(response_future.is_ok(), true); @@ -266,9 +275,36 @@ mod async_resolver_test { let conn_tcp:ClientTCPConnection = ClientTCPConnection::new(google_server, timeout); let config = ResolverConfig::default(); + let record_type = Qtype::A; let name_servers = vec![(conn_udp,conn_tcp)]; - lookup_stub(domain_name, cache, name_servers, waker,query,config).await; + lookup_stub(domain_name,record_type, cache, name_servers, waker,query,config).await; } + + #[tokio::test] + async fn lookup_stub_ns_response() { + let domain_name = DomainName::new_from_string("example.com".to_string()); + let cache = DnsCache::new(); + let waker = None; + + let query = Arc::new(Mutex::new(future::err(ResolverError::Message("Empty")).boxed())); + + // Create vect of name servers + let google_server:IpAddr = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)); + let timeout: Duration = Duration::from_secs(20); + + let conn_udp:ClientUDPConnection = ClientUDPConnection::new(google_server, timeout); + let conn_tcp:ClientTCPConnection = ClientTCPConnection::new(google_server, timeout); + + let config = ResolverConfig::default(); + let record_type = Qtype::A; + + let name_servers = vec![(conn_udp,conn_tcp)]; + lookup_stub(domain_name, record_type, cache, name_servers, waker,query,config).await; + + } + + //TODO: lookup_stub para diferentes qtype + } \ No newline at end of file