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