auto.rs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. use log::*;
  2. use dns::{Request, Response};
  3. use super::{Transport, Error, UdpTransport, TcpTransport};
  4. /// The **automatic transport**, which sends DNS wire data using the UDP
  5. /// transport, then tries using the TCP transport if the first one fails
  6. /// because the response wouldn't fit in a single UDP packet.
  7. ///
  8. /// This is the default behaviour for many DNS clients.
  9. ///
  10. /// # Examples
  11. ///
  12. /// ```no_run
  13. /// use dns_transport::{Transport, AutoTransport};
  14. /// use dns::{Request, Flags, Query, Labels, QClass, qtype, record::NS};
  15. ///
  16. /// let query = Query {
  17. /// qname: Labels::encode("dns.lookup.dog").unwrap(),
  18. /// qclass: QClass::IN,
  19. /// qtype: qtype!(NS),
  20. /// };
  21. ///
  22. /// let request = Request {
  23. /// transaction_id: 0xABCD,
  24. /// flags: Flags::query(),
  25. /// query: query,
  26. /// additional: None,
  27. /// };
  28. ///
  29. /// let transport = AutoTransport::new("8.8.8.8");
  30. /// transport.send(&request);
  31. /// ```
  32. pub struct AutoTransport {
  33. addr: String,
  34. }
  35. impl AutoTransport {
  36. /// Creates a new automatic transport that connects to the given host.
  37. pub fn new(sa: impl Into<String>) -> Self {
  38. let addr = sa.into();
  39. Self { addr }
  40. }
  41. }
  42. impl Transport for AutoTransport {
  43. fn send(&self, request: &Request) -> Result<Response, Error> {
  44. let udp_transport = UdpTransport::new(&self.addr);
  45. let udp_response = udp_transport.send(&request)?;
  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)?;
  52. Ok(tcp_response)
  53. }
  54. }