hickory_server/server/
request_handler.rs

1// Copyright 2015-2021 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Request Handler for incoming requests
9
10use std::net::SocketAddr;
11
12use hickory_proto::ProtoError;
13
14use crate::{
15    authority::MessageRequest,
16    proto::{
17        op::{Header, LowerQuery, ResponseCode},
18        xfer::Protocol,
19    },
20    server::ResponseHandler,
21};
22
23/// An incoming request to the DNS catalog
24#[derive(Debug)]
25pub struct Request {
26    /// Message with the associated query or update data
27    message: MessageRequest,
28    /// Source address of the Client
29    src: SocketAddr,
30    /// Protocol of the request
31    protocol: Protocol,
32}
33
34impl Request {
35    /// Build a new requests with the inbound message, source address, and protocol.
36    ///
37    /// This will return an error on bad verification.
38    pub fn new(message: MessageRequest, src: SocketAddr, protocol: Protocol) -> Self {
39        Self {
40            message,
41            src,
42            protocol,
43        }
44    }
45
46    /// Return just the header and request information from the Request Message
47    ///
48    /// Returns an error if there is not exactly one query
49    pub fn request_info(&self) -> Result<RequestInfo<'_>, ProtoError> {
50        Ok(RequestInfo {
51            src: self.src,
52            protocol: self.protocol,
53            header: self.message.header(),
54            query: self.message.raw_queries().try_as_query()?,
55        })
56    }
57
58    /// The IP address from which the request originated.
59    pub fn src(&self) -> SocketAddr {
60        self.src
61    }
62
63    /// The protocol that was used for the request
64    pub fn protocol(&self) -> Protocol {
65        self.protocol
66    }
67}
68
69impl std::ops::Deref for Request {
70    type Target = MessageRequest;
71
72    fn deref(&self) -> &Self::Target {
73        &self.message
74    }
75}
76
77// TODO: add ProtocolInfo that would have TLS details or other additional things...
78/// A narrow view of the Request, specifically a verified single query for the request
79#[non_exhaustive]
80#[derive(Clone)]
81pub struct RequestInfo<'a> {
82    /// The source address from which the request came
83    pub src: SocketAddr,
84    /// The protocol used for the request
85    pub protocol: Protocol,
86    /// The header from the original request
87    pub header: &'a Header,
88    /// The query from the request
89    pub query: &'a LowerQuery,
90}
91
92impl<'a> RequestInfo<'a> {
93    /// Construct a new RequestInfo
94    ///
95    /// # Arguments
96    ///
97    /// * `src` - The source address from which the request came
98    /// * `protocol` - The protocol used for the request
99    /// * `header` - The header from the original request
100    /// * `query` - The query from the request, LowerQuery is intended to reduce complexity for lookups in authorities
101    pub fn new(
102        src: SocketAddr,
103        protocol: Protocol,
104        header: &'a Header,
105        query: &'a LowerQuery,
106    ) -> Self {
107        Self {
108            src,
109            protocol,
110            header,
111            query,
112        }
113    }
114}
115
116/// Information about the response sent for a request
117#[derive(Clone, Copy, Debug)]
118#[repr(transparent)]
119pub struct ResponseInfo(Header);
120
121impl ResponseInfo {
122    pub(crate) fn serve_failed() -> Self {
123        let mut header = Header::new();
124        header.set_response_code(ResponseCode::ServFail);
125        header.into()
126    }
127}
128
129impl From<Header> for ResponseInfo {
130    fn from(header: Header) -> Self {
131        Self(header)
132    }
133}
134
135impl std::ops::Deref for ResponseInfo {
136    type Target = Header;
137
138    fn deref(&self) -> &Self::Target {
139        &self.0
140    }
141}
142
143/// Trait for handling incoming requests, and providing a message response.
144#[async_trait::async_trait]
145pub trait RequestHandler: Send + Sync + Unpin + 'static {
146    /// Determines what needs to happen given the type of request, i.e. Query or Update.
147    ///
148    /// # Arguments
149    ///
150    /// * `request` - the requested action to perform.
151    /// * `response_handle` - handle to which a return message should be sent
152    async fn handle_request<R: ResponseHandler>(
153        &self,
154        request: &Request,
155        response_handle: R,
156    ) -> ResponseInfo;
157}
158
159#[cfg(test)]
160mod tests {
161    use super::*;
162    use crate::proto::op::{Header, Query};
163
164    #[test]
165    fn request_info_clone() {
166        let query: Query = Query::new();
167        let header = Header::new();
168        let lower_query = query.into();
169        let origin = RequestInfo::new(
170            "127.0.0.1:3000".parse().unwrap(),
171            Protocol::Udp,
172            &header,
173            &lower_query,
174        );
175        let cloned = origin.clone();
176        assert_eq!(origin.header, cloned.header);
177    }
178}