auto.rs 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. use async_trait::async_trait;
  2. use log::*;
  3. use dns::{Request, Response};
  4. use super::{Transport, Error, UdpTransport, TcpTransport};
  5. /// The **automatic transport**, which uses the UDP transport, then tries
  6. /// using the TCP transport if the first one fails.
  7. ///
  8. /// # Examples
  9. ///
  10. /// ```no_run
  11. /// use dns_transport::{Transport, AutoTransport};
  12. /// use dns::{Request, Flags, Query, Labels, QClass, qtype, record::NS};
  13. ///
  14. /// let query = Query {
  15. /// qname: Labels::encode("dns.lookup.dog").unwrap(),
  16. /// qclass: QClass::IN,
  17. /// qtype: qtype!(NS),
  18. /// };
  19. ///
  20. /// let request = Request {
  21. /// transaction_id: 0xABCD,
  22. /// flags: Flags::query(),
  23. /// query: query,
  24. /// additional: None,
  25. /// };
  26. ///
  27. /// let transport = AutoTransport::new("8.8.8.8");
  28. /// transport.send(&request);
  29. /// ```
  30. #[derive(Debug)]
  31. pub struct AutoTransport {
  32. addr: String,
  33. }
  34. impl AutoTransport {
  35. /// Creates a new automatic transport that connects to the given host.
  36. pub fn new(sa: impl Into<String>) -> Self {
  37. let addr = sa.into();
  38. Self { addr }
  39. }
  40. }
  41. #[async_trait]
  42. impl Transport for AutoTransport {
  43. async fn send(&self, request: &Request) -> Result<Response, Error> {
  44. let udp_transport = UdpTransport::new(&self.addr);
  45. let udp_response = udp_transport.send(&request).await?;
  46. if ! udp_response.flags.truncated {
  47. return Ok(udp_response);
  48. }
  49. debug!("Truncated flag set, so switching to TCP");
  50. let tcp_transport = TcpTransport::new(&self.addr);
  51. let tcp_response = tcp_transport.send(&request).await?;
  52. Ok(tcp_response)
  53. }
  54. }