use std::net::SocketAddr;
use bytes::Bytes;
#[cfg(feature = "testing")]
use crate::proto::serialize::binary::{BinEncodable, BinEncoder};
use crate::{
net::{runtime::Time, xfer::Protocol},
proto::{
ProtoError,
op::{Header, HeaderCounts, LowerQuery, MessageType, Metadata, ResponseCode},
serialize::binary::{BinDecodable, BinDecoder},
},
server::ResponseHandler,
zone_handler::{LookupError, MessageRequest},
};
#[derive(Debug)]
pub struct Request {
pub(crate) message: MessageRequest,
pub(super) raw: Bytes,
pub(super) src: SocketAddr,
pub(super) protocol: Protocol,
}
impl Request {
pub fn from_bytes(
raw: Vec<u8>,
src: SocketAddr,
protocol: Protocol,
) -> Result<Self, ProtoError> {
let mut decoder = BinDecoder::new(&raw);
let header = Header::read(&mut decoder)?;
Ok(Self {
message: MessageRequest::read(&mut decoder, header)?,
raw: Bytes::from(raw),
src,
protocol,
})
}
#[cfg(feature = "testing")]
pub fn from_message(
message: MessageRequest,
src: SocketAddr,
protocol: Protocol,
) -> Result<Self, ProtoError> {
let mut encoded = Vec::new();
let mut encoder = BinEncoder::new(&mut encoded);
message.emit(&mut encoder)?;
Ok(Self {
message,
raw: Bytes::from(encoded),
src,
protocol,
})
}
pub fn request_info(&self) -> Result<RequestInfo<'_>, LookupError> {
Ok(RequestInfo {
src: self.src,
protocol: self.protocol,
metadata: &self.message.metadata,
query: self.message.queries.try_as_query()?,
})
}
pub fn src(&self) -> SocketAddr {
self.src
}
pub fn protocol(&self) -> Protocol {
self.protocol
}
pub fn as_slice(&self) -> &[u8] {
&self.raw
}
}
impl std::ops::Deref for Request {
type Target = MessageRequest;
fn deref(&self) -> &Self::Target {
&self.message
}
}
#[non_exhaustive]
#[derive(Clone)]
pub struct RequestInfo<'a> {
pub src: SocketAddr,
pub protocol: Protocol,
pub metadata: &'a Metadata,
pub query: &'a LowerQuery,
}
impl<'a> RequestInfo<'a> {
pub fn new(
src: SocketAddr,
protocol: Protocol,
metadata: &'a Metadata,
query: &'a LowerQuery,
) -> Self {
Self {
src,
protocol,
metadata,
query,
}
}
}
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct ResponseInfo(Header);
impl ResponseInfo {
pub(crate) fn serve_failed(request: &Request) -> Self {
let mut metadata = Metadata::new(
request.metadata.id,
MessageType::Response,
request.metadata.op_code,
);
metadata.response_code = ResponseCode::ServFail;
Self(Header {
metadata,
counts: HeaderCounts::default(),
})
}
pub fn counts(&self) -> HeaderCounts {
self.0.counts
}
}
impl From<Header> for ResponseInfo {
fn from(value: Header) -> Self {
Self(value)
}
}
impl std::ops::Deref for ResponseInfo {
type Target = Metadata;
fn deref(&self) -> &Self::Target {
&self.0.metadata
}
}
#[async_trait::async_trait]
pub trait RequestHandler: Send + Sync + Unpin + 'static {
async fn handle_request<R: ResponseHandler, T: Time>(
&self,
request: &Request,
response_handle: R,
) -> ResponseInfo;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::proto::op::{Metadata, OpCode, Query};
#[test]
fn request_info_clone() {
let query = Query::new();
let header = Metadata::new(10, MessageType::Query, OpCode::Query);
let lower_query = query.into();
let origin = RequestInfo::new(
"127.0.0.1:3000".parse().unwrap(),
Protocol::Udp,
&header,
&lower_query,
);
let cloned = origin.clone();
assert_eq!(origin.metadata, cloned.metadata);
}
}