[GH-ISSUE #1153] how to send a valid MessageResponse with ResponseHandler #616

Open
opened 2026-03-15 23:28:08 +03:00 by kerem · 2 comments
Owner

Originally created by @Sherlock-Holo on GitHub (Jun 26, 2020).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1153

I am learning using trust-dns-server and try to write my test server

I try the codes

use std::future::Future;
use std::net::Ipv4Addr;
use std::pin::Pin;

use trust_dns_server::authority::MessageResponseBuilder;
use trust_dns_server::proto::op::Header;
use trust_dns_server::proto::rr::{RData, Record};
use trust_dns_server::server::{Request, RequestHandler, ResponseHandler};

struct Server;

impl RequestHandler for Server {
    type ResponseFuture = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;

    fn handle_request<R: ResponseHandler>(
        &self,
        request: Request,
        response_handle: R,
    ) -> Self::ResponseFuture {
        Box::pin(async move {
            let message = request.message;

            eprintln!("request {:?}", message);

            let mut header = Header::new();
            header
                .set_id(message.id())
                .set_message_type(message.message_type())
                .set_op_code(message.op_code())
                .set_authoritative(message.authoritative())
                .set_truncated(message.truncated())
                .set_recursion_desired(message.recursion_desired())
                .set_recursion_available(message.recursion_available())
                .set_authentic_data(message.authentic_data())
                .set_checking_disabled(message.checking_disabled());

            let record = Record::from_rdata(
                message.queries()[0].name().into(),
                64,
                RData::A(Ipv4Addr::new(1, 1, 1, 1)),
            );

            let response = MessageResponseBuilder::new(Some(message.raw_queries())).build(
                header,
                Box::new(vec![record].iter()),
                Box::new(vec![].iter()),
                Box::new(vec![].iter()),
                Box::new(vec![].iter()),
            );

            response_handle.send_response(response).unwrap();
        })
    }
}

but cargo check reports an error,

error[E0308]: mismatched types
  --> src/main.rs:90:47
   |
90 |                 response_handle.send_response(response).unwrap();
   |                                               ^^^^^^^^ expected trait object `dyn std::iter::Iterator`, found struct `std::slice::Iter`
   |
   = note: expected struct `trust_dns_server::authority::message_response::MessageResponse<'_, '_, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>>`
              found struct `trust_dns_server::authority::message_response::MessageResponse<'_, '_, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `learn`.

To learn more, run the command again with --verbose.

that confuse me because I think this codes should be right

Could anyone tell me how to modify the codes

Originally created by @Sherlock-Holo on GitHub (Jun 26, 2020). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1153 I am learning using trust-dns-server and try to write my test server I try the codes ```rust use std::future::Future; use std::net::Ipv4Addr; use std::pin::Pin; use trust_dns_server::authority::MessageResponseBuilder; use trust_dns_server::proto::op::Header; use trust_dns_server::proto::rr::{RData, Record}; use trust_dns_server::server::{Request, RequestHandler, ResponseHandler}; struct Server; impl RequestHandler for Server { type ResponseFuture = Pin<Box<dyn Future<Output = ()> + Send + 'static>>; fn handle_request<R: ResponseHandler>( &self, request: Request, response_handle: R, ) -> Self::ResponseFuture { Box::pin(async move { let message = request.message; eprintln!("request {:?}", message); let mut header = Header::new(); header .set_id(message.id()) .set_message_type(message.message_type()) .set_op_code(message.op_code()) .set_authoritative(message.authoritative()) .set_truncated(message.truncated()) .set_recursion_desired(message.recursion_desired()) .set_recursion_available(message.recursion_available()) .set_authentic_data(message.authentic_data()) .set_checking_disabled(message.checking_disabled()); let record = Record::from_rdata( message.queries()[0].name().into(), 64, RData::A(Ipv4Addr::new(1, 1, 1, 1)), ); let response = MessageResponseBuilder::new(Some(message.raw_queries())).build( header, Box::new(vec![record].iter()), Box::new(vec![].iter()), Box::new(vec![].iter()), Box::new(vec![].iter()), ); response_handle.send_response(response).unwrap(); }) } } ``` but cargo check reports an error, > ``` > error[E0308]: mismatched types > --> src/main.rs:90:47 > | > 90 | response_handle.send_response(response).unwrap(); > | ^^^^^^^^ expected trait object `dyn std::iter::Iterator`, found struct `std::slice::Iter` > | > = note: expected struct `trust_dns_server::authority::message_response::MessageResponse<'_, '_, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>, std::boxed::Box<dyn std::iter::Iterator<Item = &trust_dns_proto::rr::resource::Record> + std::marker::Send>>` > found struct `trust_dns_server::authority::message_response::MessageResponse<'_, '_, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>, std::boxed::Box<std::slice::Iter<'_, trust_dns_proto::rr::resource::Record>>>` > > error: aborting due to previous error > > For more information about this error, try `rustc --explain E0308`. > error: could not compile `learn`. > > To learn more, run the command again with --verbose. > ``` that confuse me because I think this codes should be right Could anyone tell me how to modify the codes
Author
Owner

@bluejekyll commented on GitHub (Jun 29, 2020):

expected trait object dyn std::iter::Iterator, found struct std::slice::Iter

You will either need to cast this, i.e. let response = &response as &dyn Iterator or box it, let response = Box::new(response). Lifetimes would be the only reason the first wouldn't work.

<!-- gh-comment-id:651317633 --> @bluejekyll commented on GitHub (Jun 29, 2020): > expected trait object `dyn std::iter::Iterator`, found struct `std::slice::Iter` You will either need to cast this, i.e. `let response = &response as &dyn Iterator` or box it, `let response = Box::new(response)`. Lifetimes would be the only reason the first wouldn't work.
Author
Owner

@mhils commented on GitHub (Jul 5, 2020):

I ran into the same problem and what worked for me was to explicitly specify types:

let records = vec![record];
let response = MessageResponseBuilder::new(
    Some(request_message.raw_queries())
).build(
    header,
    Box::new(records.iter()) as Box<dyn Iterator<Item=&Record> + Send>,
    Box::new(iter::empty()) as Box<dyn Iterator<Item=&Record> + Send>,
    Box::new(iter::empty()) as Box<dyn Iterator<Item=&Record> + Send>,
    Box::new(iter::empty()) as Box<dyn Iterator<Item=&Record> + Send>,
);

let result = response_handle.send_response(response);

I'm not much of a Rust expert though, @bluejekyll's answer is probably more correct but less easy to parse for me :)

<!-- gh-comment-id:653831734 --> @mhils commented on GitHub (Jul 5, 2020): I ran into the same problem and what worked for me was to explicitly specify types: ```rust let records = vec![record]; let response = MessageResponseBuilder::new( Some(request_message.raw_queries()) ).build( header, Box::new(records.iter()) as Box<dyn Iterator<Item=&Record> + Send>, Box::new(iter::empty()) as Box<dyn Iterator<Item=&Record> + Send>, Box::new(iter::empty()) as Box<dyn Iterator<Item=&Record> + Send>, Box::new(iter::empty()) as Box<dyn Iterator<Item=&Record> + Send>, ); let result = response_handle.send_response(response); ``` I'm not much of a Rust expert though, @bluejekyll's answer is probably more correct but less easy to parse for me :)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#616
No description provided.