// DNS transport that retries UDP over TCP after a TC=1 response.
///|
pub struct FallbackTransport {
udp : UdpTransport
tcp : TcpTransport
}
///|
pub fn FallbackTransport::new(server : String) -> FallbackTransport {
FallbackTransport::with_options(server, default_timeout_ms, default_retries)
}
///|
pub fn FallbackTransport::with_options(
server : String,
timeout_ms : Int,
retries : Int,
udp_payload_size? : UInt16 = 1232,
) -> FallbackTransport {
{
udp: UdpTransport::with_options(
server,
timeout_ms,
retries,
udp_payload_size~,
),
tcp: TcpTransport::with_options(server, timeout_ms, retries),
}
}
///|
pub async fn FallbackTransport::send(
self : FallbackTransport,
payload : Array[Byte],
) -> Result[Array[Byte], TransportError] {
match self.udp.send(payload) {
Err(Truncated) =>
match self.tcp.send(payload) {
Ok(response) => Ok(response)
Err(_) => Err(Truncated)
}
result => result
}
}
///|
pub fn FallbackTransport::max_payload(self : FallbackTransport) -> UInt16 {
self.udp.max_payload()
}
///|
pub fn FallbackTransport::as_transport(
self : FallbackTransport,
) -> DnsTransport {
DnsTransport::from_request(
payload => self.send(payload),
udp_payload_size=self.max_payload(),
)
}
///|
pub struct FallbackStats {
udp_successes : Ref[Int]
udp_truncated : Ref[Int]
tcp_successes : Ref[Int]
tcp_failures : Ref[Int]
}
///|
pub fn FallbackStats::new() -> FallbackStats {
{
udp_successes: Ref(0),
udp_truncated: Ref(0),
tcp_successes: Ref(0),
tcp_failures: Ref(0),
}
}
///|
pub fn FallbackStats::record_udp_success(self : FallbackStats) -> Unit {
self.udp_successes.val += 1
}
///|
pub fn FallbackStats::record_truncation(self : FallbackStats) -> Unit {
self.udp_truncated.val += 1
}
///|
pub fn FallbackStats::record_tcp_success(self : FallbackStats) -> Unit {
self.tcp_successes.val += 1
}
///|
pub fn FallbackStats::record_tcp_failure(self : FallbackStats) -> Unit {
self.tcp_failures.val += 1
}
///|
pub fn FallbackStats::truncation_rate(self : FallbackStats) -> Int {
let total = self.udp_successes.val + self.udp_truncated.val
if total == 0 {
0
} else {
self.udp_truncated.val * 100 / total
}
}