Make Client and Resolver Send + Sync (#245)

* resolver is sendable

* Client and SyncClient now Clone and Send

* share cache across clones of sync Resolver

* assert Client and SyncClient are send and sync

* remove explicit ClientConnection and Client send+sync requirements

* rusls send + sync

* fix type of messagefinalizer

* everything compiling

* use rustls for client side validation of server

* fix client when all features disabled

* add type param for compatibility tests

* fix references from subject_name to dns_name

* cleanup unused errors

* ignore integration-tests lib from coverage
This commit is contained in:
Benjamin Fry 2017-11-01 05:10:07 -07:00 committed by GitHub
parent 8ac36c8525
commit d2548ad9e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 458 additions and 683 deletions

View File

@ -22,11 +22,16 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Many interfaces moved from `client::ClientStreamHandle` to `trust_dns_proto::DnsStreamHandle`
- `Message::sign` has been renamed and change to the more general method `Message::finalize`
- Some `io::Error`s have been converted to `trust_dns_proto::ProtoError`
- `SyncClient` and `SecureSyncClient` are now `Send + Sync`
### Fixed
- Server signing issues when loading from persistence
### Removed
- Removed the `NativeTls` and `OpenSSL` `ClientConnection` variants, used the Rustls impls or the tokio based `TlsClientStream` instead. This was required for `SyncClient` being `Send + Sync`
## 0.12.0
### Fixed

2
Cargo.lock generated
View File

@ -1239,11 +1239,13 @@ dependencies = [
"openssl 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"rusqlite 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"trust-dns 0.12.0",
"trust-dns-openssl 0.1.0",
"trust-dns-proto 0.1.0",
"trust-dns-resolver 0.6.0",
"trust-dns-rustls 0.1.5",
"trust-dns-server 0.12.0",
]

View File

@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::cell::{RefCell, RefMut};
use std::sync::Arc;
use std::io;
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_core::reactor::{Core, Handle};
use client::{ClientHandle, BasicClientHandle, ClientConnection, ClientFuture};
use client::{BasicClientHandle, ClientHandle, ClientConnection, ClientFuture};
#[cfg(any(feature = "openssl", feature = "ring"))]
use client::SecureClientHandle;
use error::*;
@ -42,11 +42,10 @@ use op::Message;
/// signer which can be optionally associated to the Client. This replaces the previous per-function
/// parameter, and it will sign all update requests (this matches the `ClientFuture` API).
pub trait Client<C: ClientHandle> {
/// get a mutable reference to the tokio Core associated to the Client
fn get_io_loop(&self) -> RefMut<Core>;
/// Get a mutable handle reference tot the Core associated to the Client
fn get_client_handle(&self) -> RefMut<C>;
/// Return the inner Futures items
///
/// Consumes the connection and allows for future based operations afterward.
fn new_future(&self, handle: &Handle) -> ClientResult<C>;
/// A *classic* DNS query, i.e. does not perform any DNSSec operations
///
@ -64,11 +63,10 @@ pub trait Client<C: ClientHandle> {
query_class: DNSClass,
query_type: RecordType,
) -> ClientResult<Message> {
self.get_io_loop().run(self.get_client_handle().query(
name.clone(),
query_class,
query_type,
))
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.query(name.clone(), query_class, query_type);
reactor.run(future)
}
/// Sends a NOTIFY message to the remote system
@ -89,12 +87,10 @@ pub trait Client<C: ClientHandle> {
where
R: IntoRecordSet,
{
self.get_io_loop().run(self.get_client_handle().notify(
name,
query_class,
query_type,
rrset,
))
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.notify(name, query_class, query_type, rrset);
reactor.run(future)
}
/// Sends a record to create on the server, this will fail if the record exists (atomicity
@ -134,10 +130,10 @@ pub trait Client<C: ClientHandle> {
where
R: IntoRecordSet,
{
self.get_io_loop().run(self.get_client_handle().create(
rrset,
zone_origin,
))
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.create(rrset, zone_origin);
reactor.run(future)
}
/// Appends a record to an existing rrset, optionally require the rrset to exist (atomicity
@ -183,11 +179,10 @@ pub trait Client<C: ClientHandle> {
where
R: IntoRecordSet,
{
self.get_io_loop().run(self.get_client_handle().append(
rrset,
zone_origin,
must_exist,
))
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.append(rrset, zone_origin, must_exist);
reactor.run(future)
}
/// Compares and if it matches, swaps it for the new value (atomicity depends on the server)
@ -241,13 +236,10 @@ pub trait Client<C: ClientHandle> {
CR: IntoRecordSet,
NR: IntoRecordSet,
{
self.get_io_loop().run(
self.get_client_handle().compare_and_swap(
current,
new,
zone_origin,
),
)
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.compare_and_swap(current, new, zone_origin);
reactor.run(future)
}
/// Deletes a record (by rdata) from an rrset, optionally require the rrset to exist.
@ -289,12 +281,10 @@ pub trait Client<C: ClientHandle> {
where
R: IntoRecordSet,
{
self.get_io_loop().run(
self.get_client_handle().delete_by_rdata(
record,
zone_origin,
),
)
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.delete_by_rdata(record, zone_origin);
reactor.run(future)
}
/// Deletes an entire rrset, optionally require the rrset to exist.
@ -333,12 +323,10 @@ pub trait Client<C: ClientHandle> {
/// The update must go to a zone authority (i.e. the server used in the ClientConnection). If
/// the rrset does not exist and must_exist is false, then the RRSet will be deleted.
fn delete_rrset(&self, record: Record, zone_origin: domain::Name) -> ClientResult<Message> {
self.get_io_loop().run(
self.get_client_handle().delete_rrset(
record,
zone_origin,
),
)
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.delete_rrset(record, zone_origin);
reactor.run(future)
}
/// Deletes all records at the specified name
@ -371,11 +359,10 @@ pub trait Client<C: ClientHandle> {
zone_origin: domain::Name,
dns_class: DNSClass,
) -> ClientResult<Message> {
self.get_io_loop().run(self.get_client_handle().delete_all(
name_of_records,
zone_origin,
dns_class,
))
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.delete_all(name_of_records, zone_origin, dns_class);
reactor.run(future)
}
}
@ -384,28 +371,25 @@ pub trait Client<C: ClientHandle> {
///
/// Usage of TCP or UDP is up to the user. Some DNS servers
/// disallow TCP in some cases, so if TCP double check if UDP works.
pub struct SyncClient {
client_handle: RefCell<BasicClientHandle>,
io_loop: RefCell<Core>,
pub struct SyncClient<CC> {
conn: CC,
signer: Option<Arc<Signer>>,
}
impl SyncClient {
impl<CC> SyncClient<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static
{
/// Creates a new DNS client with the specified connection type
///
/// # Arguments
///
/// * `client_connection` - the client_connection to use for all communication
pub fn new<CC: ClientConnection>(client_connection: CC) -> SyncClient
where
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
let (io_loop, stream, stream_handle) = client_connection.unwrap();
let client = ClientFuture::new(stream, stream_handle, &io_loop.handle(), None);
/// * `conn` - the [`ClientConnection`] to use for all communication
pub fn new(conn: CC) -> Self {
SyncClient {
client_handle: RefCell::new(client),
io_loop: RefCell::new(io_loop),
conn,
signer: None
}
}
@ -415,54 +399,48 @@ impl SyncClient {
///
/// # Arguments
///
/// * `client_connection` - the client_connection to use for all communication
/// * `conn` - the [`ClientConnection`] to use for all communication
/// * `signer` - signer to use, this needs an associated private key
pub fn with_signer<CC: ClientConnection>(client_connection: CC, signer: Signer) -> SyncClient
where
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
let (io_loop, stream, stream_handle) = client_connection.unwrap();
let client = ClientFuture::new(stream, stream_handle, &io_loop.handle(), Some(signer));
SyncClient {
client_handle: RefCell::new(client),
io_loop: RefCell::new(io_loop),
}
pub fn with_signer(conn: CC, signer: Signer) -> Self {
SyncClient { conn, signer: Some(Arc::new(signer)) }
}
}
impl Client<BasicClientHandle> for SyncClient {
fn get_io_loop(&self) -> RefMut<Core> {
self.io_loop.borrow_mut()
}
impl<CC> Client<BasicClientHandle> for SyncClient<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error>
+ 'static,
{
fn new_future(&self, handle: &Handle) -> ClientResult<BasicClientHandle> {
let (stream, stream_handle) = self.conn.new_stream(handle)?;
fn get_client_handle(&self) -> RefMut<BasicClientHandle> {
self.client_handle.borrow_mut()
let client = ClientFuture::new(stream, stream_handle, &handle, self.signer.clone());
Ok(client)
}
}
/// A DNS client which will validate DNSSec records upon receipt
#[cfg(any(feature = "openssl", feature = "ring"))]
pub struct SecureSyncClient {
client_handle: RefCell<SecureClientHandle<BasicClientHandle>>,
io_loop: RefCell<Core>,
#[cfg(feature = "dnssec")]
pub struct SecureSyncClient<CC> {
conn: CC,
signer: Option<Arc<Signer>>,
}
#[cfg(any(feature = "openssl", feature = "ring"))]
impl SecureSyncClient {
#[cfg(feature = "dnssec")]
impl<CC> SecureSyncClient<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
/// Creates a new DNS client with the specified connection type
///
/// # Arguments
///
/// * `client_connection` - the client_connection to use for all communication
pub fn new<CC>(client_connection: CC) -> SecureSyncClientBuilder<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
pub fn new(conn: CC) -> SecureSyncClientBuilder<CC> {
SecureSyncClientBuilder {
client_connection: client_connection,
conn: conn,
trust_anchor: None,
signer: None,
}
@ -472,24 +450,24 @@ impl SecureSyncClient {
/// validated against the trust_anchor.
///
/// *Deprecated* This function only exists for backward compatibility. It's just a wrapper around `Client::query` at this point
///
/// When the resolver receives an answer via the normal DNS lookup process, it then checks to
/// make sure that the answer is correct. Then starts
/// with verifying the DS and DNSKEY records at the DNS root. Then use the DS
/// records for the top level domain found at the root, e.g. 'com', to verify the DNSKEY
/// records in the 'com' zone. From there see if there is a DS record for the
/// subdomain, e.g. 'example.com', in the 'com' zone, and if there is use the
/// DS record to verify a DNSKEY record found in the 'example.com' zone. Finally,
/// verify the RRSIG record found in the answer for the rrset, e.g. 'www.example.com'.
///
/// *Note* As of now, this will not recurse on PTR or CNAME record responses, that is up to
/// the caller.
///
/// # Arguments
///
/// * `query_name` - the label to lookup
/// * `query_class` - most likely this should always be DNSClass::IN
/// * `query_type` - record type to lookup
///
/// When the resolver receives an answer via the normal DNS lookup process, it then checks to
/// make sure that the answer is correct. Then starts
/// with verifying the DS and DNSKEY records at the DNS root. Then use the DS
/// records for the top level domain found at the root, e.g. 'com', to verify the DNSKEY
/// records in the 'com' zone. From there see if there is a DS record for the
/// subdomain, e.g. 'example.com', in the 'com' zone, and if there is use the
/// DS record to verify a DNSKEY record found in the 'example.com' zone. Finally,
/// verify the RRSIG record found in the answer for the rrset, e.g. 'www.example.com'.
///
/// *Note* As of now, this will not recurse on PTR or CNAME record responses, that is up to
/// the caller.
///
/// # Arguments
///
/// * `query_name` - the label to lookup
/// * `query_class` - most likely this should always be DNSClass::IN
/// * `query_type` - record type to lookup
#[deprecated(note = "use `Client::query` instead")]
pub fn secure_query(
&self,
@ -497,40 +475,48 @@ impl SecureSyncClient {
query_class: DNSClass,
query_type: RecordType,
) -> ClientResult<Message> {
self.get_io_loop().run(self.get_client_handle().query(
let mut reactor = Core::new()?;
let mut client = self.new_future(&reactor.handle())?;
let future = client.query(
query_name.clone(),
query_class,
query_type,
))
);
reactor.run(future)
}
}
#[cfg(any(feature = "openssl", feature = "ring"))]
impl Client<SecureClientHandle<BasicClientHandle>> for SecureSyncClient {
fn get_io_loop(&self) -> RefMut<Core> {
self.io_loop.borrow_mut()
}
#[cfg(feature = "dnssec")]
impl<CC> Client<SecureClientHandle<BasicClientHandle>> for SecureSyncClient<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
fn new_future(&self, handle: &Handle) -> ClientResult<SecureClientHandle<BasicClientHandle>> {
let (stream, stream_handle) = self.conn.new_stream(handle)?;
fn get_client_handle(&self) -> RefMut<SecureClientHandle<BasicClientHandle>> {
self.client_handle.borrow_mut()
let client = ClientFuture::new(stream, stream_handle, &handle, self.signer.clone());
Ok(SecureClientHandle::new(client))
}
}
#[cfg(any(feature = "openssl", feature = "ring"))]
#[cfg(feature = "dnssec")]
pub struct SecureSyncClientBuilder<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
client_connection: CC,
conn: CC,
trust_anchor: Option<TrustAnchor>,
signer: Option<Signer>,
signer: Option<Arc<Signer>>,
}
#[cfg(any(feature = "openssl", feature = "ring"))]
#[cfg(feature = "dnssec")]
impl<CC> SecureSyncClientBuilder<CC>
where CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item=Vec<u8>, Error=io::Error> + 'static {
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item=Vec<u8>, Error=io::Error> + 'static
{
/// This variant allows for the trust_anchor to be replaced
///
@ -551,21 +537,36 @@ where CC: ClientConnection,
///
/// * `signer` - signer to use, this needs an associated private key
pub fn signer(mut self, signer: Signer) -> Self {
self.signer = Some(signer);
self.signer = Some(Arc::new(signer));
self
}
pub fn build(self) -> SecureSyncClient {
let (io_loop, stream, stream_handle) = self.client_connection.unwrap();
let client = ClientFuture::new(
stream,
stream_handle,
&io_loop.handle(),
self.signer);
let client = SecureClientHandle::with_trust_anchor(client, self.trust_anchor.unwrap_or(Default::default()));
SecureSyncClient{ client_handle: RefCell::new(client), io_loop: RefCell::new(io_loop) }
pub fn build(self) -> SecureSyncClient<CC> {
SecureSyncClient {
conn: self.conn,
signer: self.signer,
}
}
}
#[cfg(test)]
fn assert_send_and_sync<T: Send + Sync>() {
assert!(true)
}
#[test]
fn test_sync_client_send_and_sync() {
use udp::UdpClientConnection;
use tcp::TcpClientConnection;
assert_send_and_sync::<SyncClient<UdpClientConnection>>();
assert_send_and_sync::<SyncClient<TcpClientConnection>>();
}
#[test]
#[cfg(feature = "dnssec")]
fn test_secure_client_send_and_sync() {
use udp::UdpClientConnection;
use tcp::TcpClientConnection;
assert_send_and_sync::<SecureSyncClient<UdpClientConnection>>();
assert_send_and_sync::<SecureSyncClient<TcpClientConnection>>();
}

View File

@ -17,7 +17,7 @@
use std::io;
use futures::Future;
use tokio_core::reactor::Core;
use tokio_core::reactor::Handle;
use trust_dns_proto::DnsStreamHandle;
@ -31,7 +31,5 @@ pub trait ClientConnection: Sized {
/// Return the inner Futures items
///
/// Consumes the connection and allows for future based operations afterward.
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>);
fn new_stream(&self, handle: &Handle) -> ClientResult<(Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>)>;
}

View File

@ -5,6 +5,7 @@
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use std::sync::Arc;
use std::marker::PhantomData;
use std::io;
use std::time::Duration;
@ -46,7 +47,7 @@ impl<S: Stream<Item = Vec<u8>, Error = io::Error> + 'static> ClientFuture<S> {
stream: Box<Future<Item = S, Error = io::Error>>,
stream_handle: Box<ClientStreamHandle<Error = ClientError>>,
loop_handle: &Handle,
signer: Option<Signer>,
signer: Option<Arc<Signer>>,
) -> BasicClientHandle {
Self::with_timeout(
stream,
@ -74,7 +75,7 @@ impl<S: Stream<Item = Vec<u8>, Error = io::Error> + 'static> ClientFuture<S> {
stream_handle: Box<DnsStreamHandle<Error = ClientError>>,
loop_handle: &Handle,
timeout_duration: Duration,
finalizer: Option<Signer>,
finalizer: Option<Arc<Signer>>,
) -> BasicClientHandle {
let dns_future_handle = DnsFuture::with_timeout(
stream,

View File

@ -253,6 +253,7 @@ pub struct Signer {
/// Placeholder type for when OpenSSL and *ring* are disabled; enable OpenSSL and Ring for support
#[cfg(not(any(feature = "openssl", feature = "ring")))]
#[derive(Clone)]
pub struct Signer;
#[cfg(any(feature = "openssl", feature = "ring"))]
@ -585,6 +586,15 @@ mod tests {
pub use super::*;
fn assert_send_and_sync<T: Send + Sync>() {
assert!(true)
}
#[test]
fn test_send_and_sync() {
assert_send_and_sync::<Signer>();
}
fn pre_sig0(signer: &Signer, inception_time: u32, expiration_time: u32) -> SIG {
SIG::new(
// type covered in SIG(0) is 0 which is what makes this SIG0 vs a standard SIG

View File

@ -20,20 +20,20 @@ use std::time::Duration;
use futures::Future;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_core::reactor::Handle;
use trust_dns_proto::DnsStreamHandle;
use error::*;
use client::{ClientConnection, ClientStreamHandle};
use client::ClientConnection;
use tcp::TcpClientStream;
/// Tcp client connection
///
/// Use with `trust_dns::client::Client` impls
#[derive(Clone)]
pub struct TcpClientConnection {
io_loop: Core,
tcp_client_stream: Box<Future<Item = TcpClientStream<TcpStream>, Error = io::Error>>,
client_stream_handle: Box<ClientStreamHandle<Error = ClientError>>,
name_server: SocketAddr,
timeout: Duration,
}
impl TcpClientConnection {
@ -60,14 +60,9 @@ impl TcpClientConnection {
///
/// * `name_server` - address of the name server to use for queries
pub fn with_timeout(name_server: SocketAddr, timeout: Duration) -> ClientResult<Self> {
let io_loop = try!(Core::new());
let (tcp_client_stream, handle) =
TcpClientStream::<TcpStream>::with_timeout(name_server, &io_loop.handle(), timeout);
Ok(TcpClientConnection {
io_loop: io_loop,
tcp_client_stream: tcp_client_stream,
client_stream_handle: handle,
name_server,
timeout,
})
}
}
@ -75,13 +70,17 @@ impl TcpClientConnection {
impl ClientConnection for TcpClientConnection {
type MessageStream = TcpClientStream<TcpStream>;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
(
self.io_loop,
self.tcp_client_stream,
self.client_stream_handle,
)
fn new_stream(
&self,
handle: &Handle,
) -> ClientResult<
(Box<Future<Item = Self::MessageStream, Error = io::Error>>,
Box<DnsStreamHandle<Error = ClientError>>),
> {
let (tcp_client_stream, handle) =
TcpClientStream::<TcpStream>::with_timeout(self.name_server, handle, self.timeout);
Ok((tcp_client_stream, handle))
}
}

View File

@ -18,20 +18,19 @@ use std::io;
use std::net::SocketAddr;
use futures::Future;
use tokio_core::reactor::Core;
use tokio_core::reactor::Handle;
use trust_dns_proto::DnsStreamHandle;
use error::*;
use client::{ClientConnection, ClientStreamHandle};
use client::ClientConnection;
use udp::UdpClientStream;
/// UDP based DNS Client connection
///
/// Use with `trust_dns::client::Client` impls
#[derive(Clone)]
pub struct UdpClientConnection {
io_loop: Core,
udp_client_stream: Box<Future<Item = UdpClientStream, Error = io::Error>>,
client_stream_handle: Box<ClientStreamHandle<Error = ClientError>>,
name_server: SocketAddr,
}
impl UdpClientConnection {
@ -44,27 +43,22 @@ impl UdpClientConnection {
///
/// * `name_server` - address of the name server to use for queries
pub fn new(name_server: SocketAddr) -> ClientResult<Self> {
let io_loop = try!(Core::new());
let (udp_client_stream, handle) = UdpClientStream::new(name_server, &io_loop.handle());
Ok(UdpClientConnection {
io_loop: io_loop,
udp_client_stream: udp_client_stream,
client_stream_handle: handle,
})
Ok(UdpClientConnection { name_server })
}
}
impl ClientConnection for UdpClientConnection {
type MessageStream = UdpClientStream;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
(
self.io_loop,
self.udp_client_stream,
self.client_stream_handle,
)
fn new_stream(
&self,
handle: &Handle,
) -> ClientResult<
(Box<Future<Item = Self::MessageStream, Error = io::Error>>,
Box<DnsStreamHandle<Error = ClientError>>),
> {
let (udp_client_stream, handle) = UdpClientStream::new(self.name_server, handle);
Ok((udp_client_stream, handle))
}
}

View File

@ -54,7 +54,7 @@ fn test_get() {
}
}
fn create_sig0_ready_client<CC>(conn: CC) -> SyncClient
fn create_sig0_ready_client<CC>(conn: CC) -> SyncClient<CC>
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,

View File

@ -63,10 +63,12 @@ futures = "^0.1.6"
openssl = { version = "^0.9.8", features = ["v102", "v110"] }
rand = "^0.3"
rusqlite = { version = "^0.9.5", features = ["bundled"] }
rustls = { version = "^0.11.0" }
tokio-core = "^0.1"
trust-dns = { version = "*", path = "../client" }
trust-dns-openssl = { version = "*", path = "../openssl" }
trust-dns-proto = { version = "*", path = "../proto" }
trust-dns-resolver = { version = "*", path = "../resolver" }
trust-dns-rustls = { version = "*", path = "../rustls" }
trust-dns-server = { version = "*", path = "../server" }

View File

@ -8,6 +8,7 @@ extern crate trust_dns;
extern crate trust_dns_proto;
extern crate trust_dns_server;
use std::sync::Arc;
use std::fmt;
use std::io;
@ -15,7 +16,7 @@ use futures::{Async, Future, finished, Poll};
use futures::stream::{Fuse, Stream};
use futures::sync::mpsc::{unbounded, UnboundedReceiver};
use futures::task;
use tokio_core::reactor::Core;
use tokio_core::reactor::Handle;
use trust_dns::error::{ClientError, ClientResult};
use trust_dns::client::ClientConnection;
@ -32,14 +33,14 @@ pub mod mock_client;
#[allow(unused)]
pub struct TestClientStream {
catalog: Catalog,
catalog: Arc<Catalog>,
outbound_messages: Fuse<UnboundedReceiver<Vec<u8>>>,
}
#[allow(unused)]
impl TestClientStream {
pub fn new<E: FromProtoError>(
catalog: Catalog,
catalog: Arc<Catalog>,
) -> (Box<Future<Item = Self, Error = io::Error>>, StreamHandle<E>) {
let (message_sender, outbound_messages) = unbounded();
let message_sender = StreamHandle::new(message_sender);
@ -143,31 +144,21 @@ impl fmt::Debug for NeverReturnsClientStream {
}
#[allow(dead_code)]
pub struct NeverReturnsClientConnection {
io_loop: Core,
client_stream: Box<Future<Item = NeverReturnsClientStream, Error = io::Error>>,
client_stream_handle: StreamHandle<ClientError>,
}
pub struct NeverReturnsClientConnection {}
impl NeverReturnsClientConnection {
pub fn new() -> ClientResult<Self> {
let io_loop = try!(Core::new());
let (client_stream, handle) = NeverReturnsClientStream::new();
Ok(NeverReturnsClientConnection {
io_loop: io_loop,
client_stream: client_stream,
client_stream_handle: handle,
})
Ok(NeverReturnsClientConnection {})
}
}
impl ClientConnection for NeverReturnsClientConnection {
type MessageStream = NeverReturnsClientStream;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
(self.io_loop, self.client_stream, Box::new(self.client_stream_handle))
fn new_stream(&self, _: &Handle) -> ClientResult<(Box<Future<Item = Self::MessageStream, Error = io::Error>>,
Box<DnsStreamHandle<Error = ClientError>>)> {
let (client_stream, handle) = NeverReturnsClientStream::new();
Ok((client_stream, Box::new(handle)))
}
}

View File

@ -9,6 +9,7 @@ extern crate trust_dns_integration;
use std::net::*;
use std::cmp::Ordering;
use std::sync::Arc;
use chrono::Duration;
use futures::Future;
@ -35,7 +36,7 @@ fn test_query_nonet() {
catalog.upsert(authority.origin().clone(), authority);
let mut io_loop = Core::new().unwrap();
let (stream, sender) = TestClientStream::new(catalog);
let (stream, sender) = TestClientStream::new(Arc::new(catalog));
let mut client = ClientFuture::new(stream, Box::new(sender), &io_loop.handle(), None);
io_loop.run(test_query(&mut client)).unwrap();
@ -157,7 +158,7 @@ fn test_notify() {
catalog.upsert(authority.origin().clone(), authority);
let mut io_loop = Core::new().unwrap();
let (stream, sender) = TestClientStream::new(catalog);
let (stream, sender) = TestClientStream::new(Arc::new(catalog));
let mut client = ClientFuture::new(stream, Box::new(sender), &io_loop.handle(), None);
let name = domain::Name::from_labels(vec!["ping", "example", "com"]);
@ -207,8 +208,8 @@ fn create_sig0_ready_client(io_loop: &Core) -> (BasicClientHandle, domain::Name)
let mut catalog = Catalog::new();
catalog.upsert(authority.origin().clone(), authority);
let (stream, sender) = TestClientStream::new(catalog);
let client = ClientFuture::new(stream, Box::new(sender), &io_loop.handle(), Some(signer));
let (stream, sender) = TestClientStream::new(Arc::new(catalog));
let client = ClientFuture::new(stream, Box::new(sender), &io_loop.handle(), Some(Arc::new(signer)));
(client, origin)
}

View File

@ -5,50 +5,55 @@ extern crate tokio_core;
extern crate trust_dns;
extern crate trust_dns_integration;
extern crate trust_dns_proto;
extern crate trust_dns_rustls;
extern crate trust_dns_server;
use std::io;
use std::net::*;
use std::sync::Arc;
use std::time;
use chrono::Duration;
use futures::Future;
use futures::{Future, Stream};
use openssl::rsa::Rsa;
use tokio_core::reactor::Core;
use tokio_core::reactor::Handle;
#[allow(deprecated)]
use trust_dns::client::{Client, ClientConnection, SecureSyncClient, SyncClient};
use trust_dns::error::ClientError;
use trust_dns::error::{ClientError, ClientResult};
use trust_dns::op::*;
use trust_dns::rr::{DNSClass, Record, RecordType, domain, RData};
use trust_dns::rr::dnssec::{Algorithm, KeyPair, Signer, TrustAnchor};
use trust_dns::rr::dnssec::{Algorithm, KeyPair, Signer};
use trust_dns::rr::rdata::*;
use trust_dns::tcp::TcpClientConnection;
use trust_dns::udp::UdpClientConnection;
use trust_dns_proto::DnsStreamHandle;
use trust_dns_server::authority::Catalog;
use trust_dns_integration::{TestClientStream, NeverReturnsClientConnection};
use trust_dns_integration::authority::{create_example, create_secure_example};
use trust_dns_integration::authority::create_example;
pub struct TestClientConnection {
catalog: Catalog,
catalog: Arc<Catalog>,
}
impl TestClientConnection {
pub fn new(catalog: Catalog) -> TestClientConnection {
TestClientConnection { catalog: catalog }
TestClientConnection { catalog: Arc::new(catalog) }
}
}
impl ClientConnection for TestClientConnection {
type MessageStream = TestClientStream;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
let io_loop = Core::new().unwrap();
let (stream, handle) = TestClientStream::new(self.catalog);
(io_loop, stream, Box::new(handle))
fn new_stream(
&self,
_: &Handle,
) -> ClientResult<
(Box<Future<Item = Self::MessageStream, Error = io::Error>>,
Box<DnsStreamHandle<Error = ClientError>>),
> {
let (stream, handle) = TestClientStream::new(self.catalog.clone());
Ok((stream, Box::new(handle)))
}
}
@ -87,7 +92,11 @@ fn test_query_tcp() {
}
#[allow(deprecated)]
fn test_query(client: SyncClient) {
fn test_query<CC>(client: SyncClient<CC>)
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static
{
use std::cmp::Ordering;
let name = domain::Name::from_labels(vec!["WWW", "example", "com"]);
@ -119,36 +128,6 @@ fn test_query(client: SyncClient) {
}
}
#[test]
#[allow(deprecated)]
fn test_secure_query_example_nonet() {
let authority = create_secure_example();
let trust_anchor = {
let signers = authority.secure_keys();
let public_key = signers
.first()
.expect("expected a key in the authority")
.key()
.to_public_key()
.expect("could not convert keypair to public_key");
let mut trust_anchor = TrustAnchor::new();
trust_anchor.insert_trust_anchor(public_key);
trust_anchor
};
let mut catalog = Catalog::new();
catalog.upsert(authority.origin().clone(), authority);
let client = SecureSyncClient::new(TestClientConnection::new(catalog))
.trust_anchor(trust_anchor)
.build();
test_secure_query_example(client);
}
#[test]
#[ignore]
#[allow(deprecated)]
@ -172,7 +151,11 @@ fn test_secure_query_example_tcp() {
}
#[allow(deprecated)]
fn test_secure_query_example(client: SecureSyncClient) {
fn test_secure_query_example<CC>(client: SecureSyncClient<CC>)
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static
{
let name = domain::Name::from_labels(vec!["www", "example", "com"]);
let response = client.secure_query(&name, DNSClass::IN, RecordType::A);
@ -200,7 +183,11 @@ fn test_secure_query_example(client: SecureSyncClient) {
}
}
fn test_timeout_query(client: SyncClient) {
fn test_timeout_query<CC>(client: SyncClient<CC>)
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static
{
let name = domain::Name::from_labels(vec!["WWW", "example", "com"]);
let response = client.query(&name, DNSClass::IN, RecordType::A);
@ -295,35 +282,6 @@ fn test_dnssec_rollernet_td_tcp_mixed_case() {
).unwrap();
}
#[test]
#[allow(deprecated)]
fn test_nsec_query_example_nonet() {
let authority = create_secure_example();
let trust_anchor = {
let signers = authority.secure_keys();
let public_key = signers
.first()
.expect("expected a key in the authority")
.key()
.to_public_key()
.expect("could not convert keypair to public_key");
let mut trust_anchor = TrustAnchor::new();
trust_anchor.insert_trust_anchor(public_key);
trust_anchor
};
let mut catalog = Catalog::new();
catalog.upsert(authority.origin().clone(), authority);
let client = SecureSyncClient::new(TestClientConnection::new(catalog))
.trust_anchor(trust_anchor)
.build();
test_nsec_query_example::<TestClientConnection>(client);
}
#[test]
#[ignore]
#[allow(deprecated)]
@ -345,7 +303,11 @@ fn test_nsec_query_example_tcp() {
}
#[allow(deprecated)]
fn test_nsec_query_example<C: ClientConnection>(client: SecureSyncClient) {
fn test_nsec_query_example<CC>(client: SecureSyncClient<CC>)
where
CC: ClientConnection,
<CC as ClientConnection>::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static
{
let name = domain::Name::from_labels(vec!["none", "example", "com"]);
let response = client.secure_query(&name, DNSClass::IN, RecordType::A);
@ -411,7 +373,7 @@ fn test_nsec_query_type() {
// }
#[allow(deprecated)]
fn create_sig0_ready_client(mut catalog: Catalog) -> (SyncClient, domain::Name) {
fn create_sig0_ready_client(mut catalog: Catalog) -> (SyncClient<TestClientConnection>, domain::Name) {
let mut authority = create_example();
authority.set_allow_update(true);
let origin = authority.origin().clone();

View File

@ -33,8 +33,13 @@ fn test_lookup() {
catalog.upsert(authority.origin().clone(), authority);
let mut io_loop = Core::new().unwrap();
let (stream, sender) = TestClientStream::new(catalog);
let client = DnsFuture::new(stream, Box::new(sender), &io_loop.handle(), NoopMessageFinalizer::new());
let (stream, sender) = TestClientStream::new(Arc::new(catalog));
let client = DnsFuture::new(
stream,
Box::new(sender),
&io_loop.handle(),
NoopMessageFinalizer::new(),
);
let lookup = InnerLookupFuture::lookup(
vec![domain::Name::from_str("www.example.com.").unwrap()],
@ -56,8 +61,13 @@ fn test_lookup_hosts() {
catalog.upsert(authority.origin().clone(), authority);
let mut io_loop = Core::new().unwrap();
let (stream, sender) = TestClientStream::new(catalog);
let client = DnsFuture::new(stream, Box::new(sender), &io_loop.handle(), NoopMessageFinalizer::new());
let (stream, sender) = TestClientStream::new(Arc::new(catalog));
let client = DnsFuture::new(
stream,
Box::new(sender),
&io_loop.handle(),
NoopMessageFinalizer::new(),
);
let mut hosts = Hosts::default();

View File

@ -4,6 +4,7 @@ extern crate trust_dns_server;
extern crate trust_dns_integration;
use std::net::*;
use std::sync::Arc;
use tokio_core::reactor::Core;
@ -222,7 +223,7 @@ where
catalog.upsert(authority.origin().clone(), authority);
let io_loop = Core::new().unwrap();
let (stream, sender) = TestClientStream::new(catalog);
let (stream, sender) = TestClientStream::new(Arc::new(catalog));
let client = ClientFuture::new(stream, Box::new(sender), &io_loop.handle(), None);
let client = MemoizeClientHandle::new(client);
let secure_client = SecureClientHandle::with_trust_anchor(client, trust_anchor);

View File

@ -1,11 +1,16 @@
extern crate futures;
extern crate openssl;
extern crate rustls;
extern crate trust_dns;
extern crate trust_dns_openssl;
extern crate trust_dns_server;
extern crate trust_dns_integration;
extern crate trust_dns_openssl;
extern crate trust_dns_rustls;
extern crate trust_dns_server;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket, TcpListener};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
@ -13,22 +18,15 @@ use std::thread;
use std::time::Duration;
use futures::Stream;
use openssl::asn1::*;
use openssl::bn::*;
use openssl::hash::MessageDigest;
use openssl::nid;
use openssl::pkcs12::Pkcs12;
use openssl::pkey::PKey;
use openssl::rsa::Rsa;
use openssl::x509::*;
use openssl::x509::extension::*;
use rustls::Certificate;
use trust_dns::client::*;
use trust_dns::op::*;
use trust_dns::rr::*;
use trust_dns::udp::UdpClientConnection;
use trust_dns::tcp::TcpClientConnection;
use trust_dns_openssl::TlsClientConnection;
use trust_dns_rustls::TlsClientConnection;
use trust_dns_server::ServerFuture;
use trust_dns_server::authority::*;
@ -89,67 +87,27 @@ fn test_server_www_tcp() {
server_thread.join().unwrap();;
}
fn read_file(path: &str) -> Vec<u8> {
let mut bytes = vec![];
let mut file = File::open(path).expect(&format!("failed to open file: {}", path));
file.read_to_end(&mut bytes).expect(&format!(
"failed to read file: {}",
path
));
bytes
}
#[test]
fn test_server_www_tls() {
let subject_name = "ns.example.com";
let rsa = Rsa::generate(2048).unwrap();
let pkey = PKey::from_rsa(rsa).unwrap();
let dns_name = "ns.example.com";
let mut x509_name = X509NameBuilder::new().unwrap();
x509_name
.append_entry_by_nid(nid::COMMONNAME, subject_name)
.unwrap();
let x509_name = x509_name.build();
let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or("../server".to_owned());
println!("using server src path: {}", server_path);
let mut serial: BigNum = BigNum::new().unwrap();
serial.pseudo_rand(32, MSB_MAYBE_ZERO, false).unwrap();
let serial = serial.to_asn1_integer().unwrap();
let cert_der = read_file(&format!("{}/../tests/ca.der", server_path));
let mut x509_build = X509::builder().unwrap();
x509_build
.set_not_before(&Asn1Time::days_from_now(0).unwrap())
.unwrap();
x509_build
.set_not_after(&Asn1Time::days_from_now(256).unwrap())
.unwrap();
x509_build.set_issuer_name(&x509_name).unwrap();
x509_build.set_subject_name(&x509_name).unwrap();
x509_build.set_pubkey(&pkey).unwrap();
x509_build.set_serial_number(&serial).unwrap();
let ext_key_usage = ExtendedKeyUsage::new()
.client_auth()
.server_auth()
.build()
.unwrap();
x509_build.append_extension(ext_key_usage).unwrap();
let subject_key_identifier = SubjectKeyIdentifier::new()
.build(&x509_build.x509v3_context(None, None))
.unwrap();
x509_build.append_extension(subject_key_identifier).unwrap();
let authority_key_identifier = AuthorityKeyIdentifier::new()
.keyid(true)
.build(&x509_build.x509v3_context(None, None))
.unwrap();
x509_build
.append_extension(authority_key_identifier)
.unwrap();
// CA:FALSE
let basic_constraints = BasicConstraints::new().critical().build().unwrap();
x509_build.append_extension(basic_constraints).unwrap();
x509_build.sign(&pkey, MessageDigest::sha256()).unwrap();
let cert = x509_build.build();
let cert_der = cert.to_der().unwrap();
let pkcs12_builder = Pkcs12::builder();
let pkcs12 = pkcs12_builder
.build("mypass", subject_name, &pkey, &cert)
.unwrap();
let pkcs12_der = pkcs12.to_der().unwrap();
let pkcs12_der = read_file(&format!("{}/../tests/cert.p12", server_path));
// Server address
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
@ -170,7 +128,7 @@ fn test_server_www_tls() {
let client_thread = thread::Builder::new()
.name("test_server:tcp:client".to_string())
.spawn(move || {
client_thread_www(lazy_tls_client(ipaddr, subject_name.to_string(), cert_der))
client_thread_www(lazy_tls_client(ipaddr, dns_name.to_string(), cert_der))
})
.unwrap();
@ -189,17 +147,13 @@ fn lazy_tcp_client(ipaddr: SocketAddr) -> TcpClientConnection {
TcpClientConnection::new(ipaddr).unwrap()
}
fn lazy_tls_client(
ipaddr: SocketAddr,
subject_name: String,
cert_der: Vec<u8>,
) -> TlsClientConnection {
fn lazy_tls_client(ipaddr: SocketAddr, dns_name: String, cert_der: Vec<u8>) -> TlsClientConnection {
let mut builder = TlsClientConnection::builder();
let trust_chain = X509::from_der(&cert_der).unwrap();
let trust_chain = Certificate(cert_der);
builder.add_ca(trust_chain);
builder.build(ipaddr, subject_name).unwrap()
builder.build(ipaddr, dns_name).unwrap()
}
fn client_thread_www<C: ClientConnection>(conn: C)

View File

@ -25,11 +25,9 @@ extern crate tokio_tls;
extern crate trust_dns;
extern crate trust_dns_proto;
pub mod tls_client_connection;
pub mod tls_client_stream;
pub mod tls_stream;
pub use self::tls_client_connection::{TlsClientConnection, TlsClientConnectionBuilder};
pub use self::tls_client_stream::{TlsClientStream, TlsClientStreamBuilder};
pub use self::tls_stream::{TlsStream, TlsStreamBuilder};

View File

@ -87,7 +87,7 @@ fn tls_client_stream_test(server_addr: IpAddr, mtls: bool) {
let root_cert_der = read_file(&format!("{}/../tests/ca.der", server_path));
// Generate X509 certificate
let subject_name = "ns.example.com";
let dns_name = "ns.example.com";
let server_pkcs12_der = read_file(&format!("{}/../tests/cert.p12", server_path));
// TODO: need a timeout on listen
@ -189,7 +189,7 @@ fn tls_client_stream_test(server_addr: IpAddr, mtls: bool) {
// config_mtls(&root_pkey, &root_name, &root_cert, &mut builder);
// }
let (stream, sender) = builder.build(server_addr, subject_name.to_string(), &io_loop.handle());
let (stream, sender) = builder.build(server_addr, dns_name.to_string(), &io_loop.handle());
// TODO: there is a race failure here... a race with the server thread most likely...
let mut stream = io_loop.run(stream).ok().expect("run failed to get stream");

View File

@ -1,104 +0,0 @@
// Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! TLS based DNS client connection for Client impls
use std::net::SocketAddr;
use std::io;
use futures::Future;
use native_tls::Certificate;
#[cfg(feature = "mtls")]
use native_tls::Pkcs12;
use tokio_core::reactor::Core;
use trust_dns::error::*;
use trust_dns::client::ClientConnection;
use trust_dns_proto::DnsStreamHandle;
use {TlsClientStream, TlsClientStreamBuilder};
/// Tls client connection
///
/// Use with `trust_dns::client::Client` impls
pub struct TlsClientConnection {
io_loop: Core,
tls_client_stream: Box<Future<Item = TlsClientStream, Error = io::Error>>,
client_stream_handle: Box<DnsStreamHandle<Error = ClientError>>,
}
impl TlsClientConnection {
/// Creates a new builder for the construction of a TlsClientConnection.
pub fn builder() -> TlsClientConnectionBuilder {
TlsClientConnectionBuilder(TlsClientStreamBuilder::new())
}
}
impl ClientConnection for TlsClientConnection {
type MessageStream = TlsClientStream;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
(
self.io_loop,
self.tls_client_stream,
self.client_stream_handle,
)
}
}
/// A builder for the TlsClientStream.
pub struct TlsClientConnectionBuilder(TlsClientStreamBuilder);
impl TlsClientConnectionBuilder {
/// Add a custom trusted peer certificate or certificate auhtority.
///
/// If this is the 'client' then the 'server' must have it associated as it's `identity`, or have had the `identity` signed by this certificate.
pub fn add_ca(&mut self, ca: Certificate) {
self.0.add_ca(ca);
}
/// Client side identity for client auth in TLS (aka mutual TLS auth)
#[cfg(feature = "mtls")]
pub fn identity(&mut self, pkcs12: Pkcs12) {
self.0.identity(pkcs12);
}
/// Creates a new client connection.
///
/// *Note* this has side affects of establishing the connection to the specified DNS server and
/// starting the event_loop. Expect this to change in the future.
///
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
) -> ClientResult<TlsClientConnection> {
let io_loop = try!(Core::new());
let (tls_client_stream, handle) =
self.0.build(name_server, subject_name, &io_loop.handle());
Ok(TlsClientConnection {
io_loop: io_loop,
tls_client_stream: tls_client_stream,
client_stream_handle: handle,
})
}
}

View File

@ -56,15 +56,15 @@ impl TlsClientStreamBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Subject Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
loop_handle: &Handle,
) -> (Box<Future<Item = TlsClientStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
let (stream_future, sender) = self.0.build(name_server, subject_name, loop_handle);
let (stream_future, sender) = self.0.build(name_server, dns_name, loop_handle);
let new_future: Box<Future<Item = TlsClientStream, Error = io::Error>> = Box::new(
stream_future.map(move |tls_stream| TcpClientStream::from_stream(tls_stream)),

View File

@ -133,12 +133,12 @@ impl TlsStreamBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
loop_handle: &Handle,
) -> (Box<Future<Item = TlsStream, Error = io::Error>>, BufStreamHandle<ClientError>) {
let (message_sender, outbound_messages) = unbounded();
@ -167,7 +167,7 @@ impl TlsStreamBuilder {
Box::new(
tcp.and_then(move |tcp_stream| {
tls_connector
.connect_async(&subject_name, tcp_stream)
.connect_async(&dns_name, tcp_stream)
.map(move |s| {
TcpStream::from_stream_with_receiver(s, name_server, outbound_messages)
})

View File

@ -23,11 +23,9 @@ extern crate tokio_openssl;
extern crate trust_dns;
extern crate trust_dns_proto;
mod tls_client_connection;
mod tls_client_stream;
pub mod tls_server;
mod tls_stream;
pub use self::tls_client_connection::{TlsClientConnection, TlsClientConnectionBuilder};
pub use self::tls_client_stream::{TlsClientStream, TlsClientStreamBuilder};
pub use self::tls_stream::{TlsStream, TlsStreamBuilder, tls_stream_from_existing_tls_stream};

View File

@ -1,102 +0,0 @@
// Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! TLS based DNS client connection for Client impls
use std::net::SocketAddr;
use std::io;
use futures::Future;
use openssl::x509::X509 as OpensslX509;
use tokio_core::reactor::Core;
use trust_dns::error::*;
use trust_dns::client::ClientConnection;
use trust_dns_proto::DnsStreamHandle;
use super::{TlsClientStream, TlsClientStreamBuilder};
/// Tls client connection
///
/// Use with `trust_dns::client::Client` impls
pub struct TlsClientConnection {
io_loop: Core,
tls_client_stream: Box<Future<Item = TlsClientStream, Error = io::Error>>,
client_stream_handle: Box<DnsStreamHandle<Error = ClientError>>,
}
impl TlsClientConnection {
/// Creates a new builder for the construction of a TlsClientConnection.
pub fn builder() -> TlsClientConnectionBuilder {
TlsClientConnectionBuilder(TlsClientStreamBuilder::new())
}
}
impl ClientConnection for TlsClientConnection {
type MessageStream = TlsClientStream;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
(
self.io_loop,
self.tls_client_stream,
self.client_stream_handle,
)
}
}
/// A builder for the TlsClientStream.
pub struct TlsClientConnectionBuilder(TlsClientStreamBuilder);
impl TlsClientConnectionBuilder {
/// Add a custom trusted peer certificate or certificate auhtority.
///
/// If this is the 'client' then the 'server' must have it associated as it's `identity`, or have had the `identity` signed by this certificate.
pub fn add_ca(&mut self, ca: OpensslX509) {
self.0.add_ca(ca);
}
/// Client side identity for client auth in TLS (aka mutual TLS auth)
#[cfg(feature = "mtls")]
pub fn identity(&mut self, pkcs12: Pkcs12) {
self.0.identity(pkcs12);
}
/// Creates a new client connection.
///
/// *Note* this has side affects of establishing the connection to the specified DNS server and
/// starting the event_loop. Expect this to change in the future.
///
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
) -> ClientResult<TlsClientConnection> {
let io_loop = try!(Core::new());
let (tls_client_stream, handle) =
self.0.build(name_server, subject_name, &io_loop.handle());
Ok(TlsClientConnection {
io_loop: io_loop,
tls_client_stream: tls_client_stream,
client_stream_handle: handle,
})
}
}

View File

@ -64,16 +64,16 @@ impl TlsClientStreamBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Subject Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
loop_handle: &Handle,
) -> (Box<Future<Item = TlsClientStream, Error = io::Error>>,
Box<DnsStreamHandle<Error = ClientError>>) {
let (stream_future, sender) = self.0.build(name_server, subject_name, loop_handle);
let (stream_future, sender) = self.0.build(name_server, dns_name, loop_handle);
let new_future: Box<Future<Item = TlsClientStream, Error = io::Error>> = Box::new(
stream_future.map(move |tls_stream| TcpClientStream::from_stream(tls_stream)),

View File

@ -178,12 +178,12 @@ impl TlsStreamBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Subject Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
loop_handle: &Handle,
) -> (Box<Future<Item = TlsStream, Error = io::Error>>, BufStreamHandle<ClientError>) {
let (message_sender, outbound_messages) = unbounded();
@ -212,7 +212,7 @@ impl TlsStreamBuilder {
Box::new(
tcp.and_then(move |tcp_stream| {
tls_connector
.connect_async(&subject_name, tcp_stream)
.connect_async(&dns_name, tcp_stream)
.map(move |s| {
TcpStream::from_stream_with_receiver(s, name_server, outbound_messages)
})

View File

@ -5,6 +5,8 @@
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use std::borrow::Borrow;
use std::sync::Arc;
use std::collections::{HashMap, HashSet};
use std::io;
use std::marker::PhantomData;
@ -80,7 +82,7 @@ where
stream_handle: Box<DnsStreamHandle<Error = E>>,
new_receiver: Peekable<StreamFuse<UnboundedReceiver<(Message, Complete<Result<Message, E>>)>>>,
active_requests: HashMap<u16, (Complete<Result<Message, E>>, Timeout)>,
signer: Option<MF>,
signer: Option<Arc<MF>>,
}
impl<S, E, MF> DnsFuture<S, E, MF>
@ -103,7 +105,7 @@ where
stream: Box<Future<Item = S, Error = io::Error>>,
stream_handle: Box<DnsStreamHandle<Error = E>>,
loop_handle: &Handle,
signer: Option<MF>,
signer: Option<Arc<MF>>,
) -> BasicDnsHandle<E> {
Self::with_timeout(
stream,
@ -131,7 +133,7 @@ where
stream_handle: Box<DnsStreamHandle<Error = E>>,
loop_handle: &Handle,
timeout_duration: Duration,
signer: Option<MF>,
signer: Option<Arc<MF>>,
) -> BasicDnsHandle<E> {
let (sender, rx) = unbounded();
@ -275,7 +277,7 @@ where
// update messages need to be signed.
if let OpCode::Update = message.op_code() {
if let Some(ref signer) = self.signer {
if let Err(e) = message.finalize(signer, now) {
if let Err(e) = message.finalize::<MF>(signer.borrow(), now) {
warn!("could not sign message: {}", e);
complete.send(Err(e.into())).expect(
"error notifying wait, possible future leak",

View File

@ -16,6 +16,7 @@
//! Basic protocol message for DNS
use std::sync::Arc;
use std::mem;
use error::*;
@ -648,7 +649,7 @@ pub struct NoopMessageFinalizer;
impl NoopMessageFinalizer {
/// Always returns None
pub fn new() -> Option<Self> {
pub fn new() -> Option<Arc<Self>> {
None
}
}

View File

@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Resolver no longer depends on Client
- *breaking* Resolver no longer returns io:Errors, use `From<ResolveError>` for `io::Error`
- Resolver is now `Send`
### Added

View File

@ -17,7 +17,7 @@ use futures::{Async, Future, Poll, task};
use trust_dns_proto::DnsHandle;
use trust_dns_proto::op::{Message, Query, ResponseCode};
use trust_dns_proto::rr::{Name, RData, RecordType};
use trust_dns_proto::rr::{RData, RecordType};
use error::*;
use lookup::Lookup;
@ -46,10 +46,10 @@ impl LruValue {
}
#[derive(Debug)]
struct DnsLru(LruCache<Query, LruValue>);
pub(crate) struct DnsLru(LruCache<Query, LruValue>);
impl DnsLru {
fn new(capacity: usize) -> Self {
pub(crate) fn new(capacity: usize) -> Self {
DnsLru(LruCache::new(capacity))
}
@ -160,7 +160,7 @@ impl<C: DnsHandle<Error = ResolveError> + 'static> CachingClient<C> {
Self::with_cache(Arc::new(Mutex::new(DnsLru::new(max_size))), client)
}
fn with_cache(lru: Arc<Mutex<DnsLru>>, client: C) -> Self {
pub(crate) fn with_cache(lru: Arc<Mutex<DnsLru>>, client: C) -> Self {
CachingClient { lru, client }
}

View File

@ -6,12 +6,11 @@
// copied, modified, or distributed except according to those terms.
//! Structs for creating and using a Resolver
use std::cell::RefCell;
use std::net::IpAddr;
use std::io;
use std::sync::{Arc, Mutex};
use tokio_core::reactor::Core;
use tokio_core::reactor::{Core, Handle};
use trust_dns_proto::rr::RecordType;
use config::{ResolverConfig, ResolverOpts};
@ -19,14 +18,18 @@ use error::*;
use lookup;
use lookup::Lookup;
use lookup_ip::LookupIp;
use lookup_state::DnsLru;
use ResolverFuture;
/// The Resolver is used for performing DNS queries.
///
/// For forward (A) lookups, hostname -> IP address, see: `Resolver::lookup_ip`
///
/// Special note about resource consumption. The Resolver and all TRust-DNS software is built around the Tokio async-io library. This synchronous Resolver is intended to be a simpler wrapper for of the [`trust_dns_resolver::ResolverFuture`]. To allow the Resolver to be [`Send`] + [`Sync`], the construction of the `ResolverFuture` is lazy, this means some of the features of the `ResolverFuture`, like performance based resolution via the most efficient `NameServer` will be lost (the lookup cache is shared across invocations of the `Resolver`). If these other features of the TRust-DNS Resolver are desired, please use the tokio based `ResolverFuture`.
pub struct Resolver {
resolver_future: RefCell<ResolverFuture>,
io_loop: RefCell<Core>,
config: ResolverConfig,
options: ResolverOpts,
lru: Arc<Mutex<DnsLru>>,
}
macro_rules! lookup_fn {
@ -39,11 +42,9 @@ macro_rules! lookup_fn {
///
/// * `query` - a str which parses to a domain name, failure to parse will return an error
pub fn $p(&self, query: &str) -> ResolveResult<$l> {
self.io_loop.borrow_mut().run(
self.resolver_future
.borrow()
.$p(query),
)
let mut reactor = Core::new()?;
let future = self.construct_and_run(&reactor.handle())?;
reactor.run(future.$p(query))
}
};
($p:ident, $l:ty, $t:ty) => {
@ -53,11 +54,9 @@ pub fn $p(&self, query: &str) -> ResolveResult<$l> {
///
/// * `query` - a type which can be converted to `Name` via `From`.
pub fn $p(&self, query: $t) -> ResolveResult<$l> {
self.io_loop.borrow_mut().run(
self.resolver_future
.borrow()
.$p(query),
)
let mut reactor = Core::new()?;
let future = self.construct_and_run(&reactor.handle())?;
reactor.run(future.$p(query))
}
};
}
@ -71,41 +70,63 @@ impl Resolver {
/// * `client_connection` - ClientConnection for establishing the connection to the DNS server
///
/// # Returns
/// A new Resolver
///
/// A new Resolver or an error if there was an error with the configuration.
pub fn new(config: ResolverConfig, options: ResolverOpts) -> io::Result<Self> {
let io_loop = Core::new()?;
let resolver = ResolverFuture::new(config, options, &io_loop.handle());
let lru = Arc::new(Mutex::new(DnsLru::new(options.cache_size)));
Ok(Resolver {
resolver_future: RefCell::new(resolver),
io_loop: RefCell::new(io_loop),
config,
options,
lru,
})
}
/// Constructs a new Resolver with default config and default options.
///
/// See [`ResolverConfig::default`] and [`ResolverOpts::default`] for more information.
///
/// # Returns
///
/// A new Resolver or an error if there was an error with the configuration.
pub fn default() -> io::Result<Self> {
Self::new(ResolverConfig::default(), ResolverOpts::default())
}
/// Constructs a new Resolver with the system configuration.
///
/// This will use `/etc/resolv.conf` on Unix OSes and the registry on Windows.
#[cfg(any(unix,
all(feature = "ipconfig", target_os = "windows", target_pointer_width = "64")))]
all(feature = "ipconfig", target_os = "windows", target_pointer_width = "64")))]
pub fn from_system_conf() -> io::Result<Self> {
let (config, options) = super::system_conf::read_system_conf()?;
Self::new(config, options)
}
/// Constructs a new Core
fn construct_and_run(&self, reactor: &Handle) -> ResolveResult<ResolverFuture> {
// TODO: get a pair of the Future and the Handle, to run on the same Core.
let future = ResolverFuture::with_cache(
self.config.clone(),
self.options.clone(),
self.lru.clone(),
reactor,
);
Ok(future)
}
/// Generic lookup for any RecordType
///
/// *WARNING* This interface may change in the future
/// *WARNING* This interface may change in the future, please use [`Self::lookkup_ip`] or another variant for more stable interfaces.
///
/// # Arguments
///
/// * `name` - name of the record to lookup, if name is not a valid domain name, an error will be returned
/// * `record_type` - type of record to lookup
pub fn lookup(&self, name: &str, record_type: RecordType) -> ResolveResult<Lookup> {
self.io_loop.borrow_mut().run(
self.resolver_future
.borrow()
.lookup(name, record_type),
)
let mut reactor = Core::new()?;
let future = self.construct_and_run(&reactor.handle())?;
reactor.run(future.lookup(name, record_type))
}
/// Performs a dual-stack DNS lookup for the IP for the given hostname.
@ -116,11 +137,9 @@ impl Resolver {
///
/// * `host` - string hostname, if this is an invalid hostname, an error will be returned.
pub fn lookup_ip(&self, host: &str) -> ResolveResult<LookupIp> {
self.io_loop.borrow_mut().run(
self.resolver_future
.borrow()
.lookup_ip(host),
)
let mut reactor = Core::new()?;
let future = self.construct_and_run(&reactor.handle())?;
reactor.run(future.lookup_ip(host))
}
/// Performs a DNS lookup for an SRV record for the specified service type and protocol at the given name.
@ -138,13 +157,9 @@ impl Resolver {
protocol: &str,
name: &str,
) -> ResolveResult<lookup::SrvLookup> {
self.io_loop.borrow_mut().run(
self.resolver_future.borrow().lookup_service(
service,
protocol,
name,
),
)
let mut reactor = Core::new()?;
let future = self.construct_and_run(&reactor.handle())?;
reactor.run(future.lookup_service(service, protocol, name))
}
lookup_fn!(reverse_lookup, lookup::ReverseLookup, IpAddr);
@ -161,6 +176,15 @@ mod tests {
use super::*;
fn require_send_sync<S: Send + Sync>() {
assert!(true);
}
#[test]
fn test_resolver_sendable() {
require_send_sync::<Resolver>();
}
#[test]
fn test_lookup() {
let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
@ -193,7 +217,7 @@ mod tests {
#[test]
#[ignore]
#[cfg(any(unix,
all(feature = "ipconfig", target_os = "windows", target_pointer_width = "64")))]
all(feature = "ipconfig", target_os = "windows", target_pointer_width = "64")))]
fn test_system_lookup() {
let resolver = Resolver::from_system_conf().unwrap();

View File

@ -8,7 +8,7 @@
//! Structs for creating and using a ResolverFuture
use std::net::IpAddr;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use futures::Future;
use tokio_core::reactor::Handle;
@ -23,11 +23,12 @@ use error::*;
use lookup_state::CachingClient;
use name_server_pool::{NameServerPool, StandardConnection};
use lookup_ip::{InnerLookupIpFuture, LookupIpFuture};
use lookup_state::DnsLru;
use lookup;
use lookup::{InnerLookupFuture, LookupEither, LookupFuture};
use hosts::Hosts;
/// Root Handle to communicate with teh ResolverFuture
/// Root Handle to communicate with the ResolverFuture
///
/// This can be used directly to perform queries. See [`trust_dns_proto::SecureClientHandle`] for
/// a DNSSEc chain validator.
@ -94,8 +95,28 @@ pub fn $p(&self, query: $t) -> $f {
}
impl ResolverFuture {
/// Construct a new ResolverFuture with the associated Client.
/// Construct a new ResolverFuture with the associated Client and configuration.
///
/// # Arguments
///
/// * `config` - configuration, name_servers, etc. for the Resolver
/// * `options` - basic lookup options for the resolver
/// * `reactor` - the [`tokio_core::Core`] to use with this future
pub fn new(config: ResolverConfig, options: ResolverOpts, reactor: &Handle) -> Self {
let lru = Arc::new(Mutex::new(DnsLru::new(options.cache_size)));
Self::with_cache(config, options, lru, reactor)
}
/// Construct a new ResolverFuture with the associated Client and configuration.
///
/// # Arguments
///
/// * `config` - configuration, name_servers, etc. for the Resolver
/// * `options` - basic lookup options for the resolver
/// * `lru` - the cache to be used with the resolver
/// * `reactor` - the [`tokio_core::Core`] to use with this future
pub(crate) fn with_cache(config: ResolverConfig, options: ResolverOpts, lru: Arc<Mutex<DnsLru>>, reactor: &Handle) -> Self {
let pool = NameServerPool::<BasicResolverHandle, StandardConnection>::from_config(
&config,
&options,
@ -126,7 +147,7 @@ impl ResolverFuture {
ResolverFuture {
config,
options,
client_cache: CachingClient::new(options.cache_size, either),
client_cache: CachingClient::with_cache(lru, either),
hosts: hosts,
}
}

View File

@ -93,7 +93,7 @@ fn tls_client_stream_test(server_addr: IpAddr, mtls: bool) {
let root_cert_der_copy = root_cert_der.clone();
// Generate X509 certificate
let subject_name = "ns.example.com";
let dns_name = "ns.example.com";
let server_pkcs12_der = read_file(&format!("{}/../tests/cert.p12", server_path));
// TODO: need a timeout on listen
@ -201,7 +201,7 @@ fn tls_client_stream_test(server_addr: IpAddr, mtls: bool) {
// config_mtls(&root_pkey, &root_name, &root_cert, &mut builder);
// }
let (stream, sender) = builder.build(server_addr, subject_name.to_string(), &io_loop.handle());
let (stream, sender) = builder.build(server_addr, dns_name.to_string(), &io_loop.handle());
// TODO: there is a race failure here... a race with the server thread most likely...
let mut stream = io_loop.run(stream).ok().expect("run failed to get stream");

View File

@ -19,7 +19,7 @@ use std::io;
use futures::Future;
use rustls::Certificate;
use tokio_core::reactor::Core;
use tokio_core::reactor::Handle;
use trust_dns::error::*;
use trust_dns::client::ClientConnection;
@ -33,9 +33,9 @@ use TlsClientStreamBuilder;
///
/// Use with `trust_dns::client::Client` impls
pub struct TlsClientConnection {
io_loop: Core,
tls_client_stream: Box<Future<Item = TlsClientStream, Error = io::Error>>,
client_stream_handle: Box<DnsStreamHandle<Error = ClientError>>,
builder: TlsClientStreamBuilder,
name_server: SocketAddr,
dns_name: String,
}
impl TlsClientConnection {
@ -47,14 +47,20 @@ impl TlsClientConnection {
impl ClientConnection for TlsClientConnection {
type MessageStream = TlsClientStream;
fn unwrap(
self,
) -> (Core, Box<Future<Item = Self::MessageStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
(
self.io_loop,
self.tls_client_stream,
self.client_stream_handle,
)
fn new_stream(
&self,
handle: &Handle,
) -> ClientResult<
(Box<Future<Item = Self::MessageStream, Error = io::Error>>,
Box<DnsStreamHandle<Error = ClientError>>),
> {
let (tls_client_stream, handle) = self.builder.clone().build(
self.name_server,
self.dns_name.clone(),
handle,
);
Ok((tls_client_stream, handle))
}
}
@ -82,21 +88,17 @@ impl TlsClientConnectionBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Subject Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
) -> ClientResult<TlsClientConnection> {
let io_loop = try!(Core::new());
let (tls_client_stream, handle) =
self.0.build(name_server, subject_name, &io_loop.handle());
Ok(TlsClientConnection {
io_loop: io_loop,
tls_client_stream: tls_client_stream,
client_stream_handle: handle,
builder: self.0,
name_server,
dns_name,
})
}
}

View File

@ -22,6 +22,7 @@ use TlsStreamBuilder;
pub type TlsClientStream = TcpClientStream<TokioTlsStream<TokioTcpStream, ClientSession>>;
#[derive(Clone)]
pub struct TlsClientStreamBuilder(TlsStreamBuilder);
impl TlsClientStreamBuilder {
@ -47,15 +48,15 @@ impl TlsClientStreamBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Subject Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
loop_handle: &Handle,
) -> (Box<Future<Item = TlsClientStream, Error = io::Error>>, Box<DnsStreamHandle<Error = ClientError>>) {
let (stream_future, sender) = self.0.build(name_server, subject_name, loop_handle);
let (stream_future, sender) = self.0.build(name_server, dns_name, loop_handle);
let new_future: Box<Future<Item = TlsClientStream, Error = io::Error>> = Box::new(
stream_future.map(move |tls_stream| TcpClientStream::from_stream(tls_stream)),

View File

@ -66,6 +66,7 @@ pub fn tls_from_stream(
(stream, message_sender)
}
#[derive(Clone)]
pub struct TlsStreamBuilder {
ca_chain: Vec<Certificate>,
//identity: Option<Pkcs12>,
@ -117,12 +118,12 @@ impl TlsStreamBuilder {
/// # Arguments
///
/// * `name_server` - IP and Port for the remote DNS resolver
/// * `subject_name` - The Subject Public Key Info (SPKI) name as associated to a certificate
/// * `dns_name` - The DNS name, Subject Public Key Info (SPKI) name, as associated to a certificate
/// * `loop_handle` - The reactor Core handle
pub fn build(
self,
name_server: SocketAddr,
subject_name: String,
dns_name: String,
loop_handle: &Handle,
) -> (Box<Future<Item = TlsStream, Error = io::Error>>, BufStreamHandle<ClientError>) {
let (message_sender, outbound_messages) = unbounded();
@ -151,7 +152,7 @@ impl TlsStreamBuilder {
Box::new(
tcp.and_then(move |tcp_stream| {
tls_connector
.connect_async(&subject_name, tcp_stream)
.connect_async(&dns_name, tcp_stream)
.map(move |s| {
TcpStream::from_stream_with_receiver(s, name_server, outbound_messages)
})

View File

@ -35,7 +35,7 @@ export TDNS_SERVER_SRC_ROOT=./server
export COVERALLS_PARALLEL=true
SRC_PATHS=client/src,native-tls/src,openssl/src,proto/src,resolver/src,rustls/src,server/src
EXCLUDE_PATHS=client/src/error,proto/src/error.rs,server/src/error
EXCLUDE_PATHS=client/src/error,proto/src/error.rs,server/src/error,compatibility-tests/src/lib.rs
for i in target/debug/deps/trust_dns*-* target/debug/deps/*_tests-* ; do
if [ -f $i ] && [ -x $i ]; then

View File

@ -20,8 +20,9 @@ use trust_dns::client::*;
use trust_dns::rr::*;
use trust_dns::tcp::TcpClientStream;
#[cfg(feature = "tls")]
use trust_dns_openssl::TlsClientStreamBuilder;
// TODO: Needed for when TLS tests are added back
// #[cfg(feature = "tls")]
// use trust_dns_openssl::TlsClientStreamBuilder;
use server_harness::{named_test_harness, query_a};