Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose danger_connect_async_without_providing_domain_for_certificate_verification_and_server_name_indication #34

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 67 additions & 11 deletions src/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,36 @@ mod encryption {
-> Box<Future<Item=AutoStream<S>, Error=Error>>
where
S: 'static + AsyncRead + AsyncWrite,
{
get_wrapped_stream(socket, domain, mode, false)
}

pub fn danger_wrap_stream<S>(socket: S, mode: Mode)
-> Box<Future<Item=AutoStream<S>, Error=Error>>
where
S: 'static + AsyncRead + AsyncWrite,
{
get_wrapped_stream(socket, String::new(), mode, true)
}

// Helper function for reducing duplicate code
fn get_wrapped_stream<S>(socket: S, domain: String, mode: Mode, dangerously: bool)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function, together with its additional parameter dangerously is actually not required. You could write it a bit simpler, by changing the signature of wrap_stream() a bit. The wrap_stream() function accepts a domain parameter, for the purpose of allowing it to perform a danger connection, you can just change the type of the domain from String to Option<String>, in this case both danger_wrap_stream() and get_wrapped_stream() are not necessary anymore, i.e. the same thing can be rewritten shorten and simplier ;)

-> Box<Future<Item=AutoStream<S>, Error=Error>>
where
S: 'static + AsyncRead + AsyncWrite,
{
match mode {
Mode::Plain => Box::new(future::ok(StreamSwitcher::Plain(socket))),
Mode::Tls => {
Box::new(future::result(TlsConnector::builder())
.and_then(move |builder| future::result(builder.build()))
.and_then(move |connector| connector.connect_async(&domain, socket))
.map(|s| StreamSwitcher::Tls(s))
.map_err(|e| Error::Tls(e)))
.and_then(move |builder| future::result(builder.build()))
.and_then(move |connector| if dangerously {
connector.danger_connect_async_without_providing_domain_for_certificate_verification_and_server_name_indication(socket)
} else {
connector.connect_async(&domain, socket)
})
.map(|s| StreamSwitcher::Tls(s))
.map_err(|e| Error::Tls(e)))
}
}
}
Expand Down Expand Up @@ -92,7 +113,7 @@ mod encryption {
}
}

use self::encryption::{AutoStream, wrap_stream};
use self::encryption::{AutoStream, wrap_stream, danger_wrap_stream};

/// Get a domain from an URL.
#[inline]
Expand Down Expand Up @@ -133,20 +154,55 @@ where
.and_then(move |stream| client_async(request, stream)))
}

/// Connect to a given URL. This version is dangerous. It doesn't check certificates.
pub fn danger_connect_async<R>(request: R, handle: Remote)
-> Box<Future<Item=(WebSocketStream<AutoStream<TcpStream>>, Response), Error=Error>>
where
R: Into<Request<'static>>
{
connect_async_helper(request, handle, true)
}


/// Connect to a given URL.
pub fn connect_async<R>(request: R, handle: Remote)
-> Box<Future<Item=(WebSocketStream<AutoStream<TcpStream>>, Response), Error=Error>>
where
R: Into<Request<'static>>
{
connect_async_helper(request, handle, false)
}

// Helper function for reducing duplicate code
fn connect_async_helper<R>(request: R, handle: Remote, dangerously: bool)
-> Box<Future<Item=(WebSocketStream<AutoStream<TcpStream>>, Response), Error=Error>>
where
R: Into<Request<'static>>
{
let request: Request = request.into();

let domain = match domain(&request) {
Ok(domain) => domain,
Err(err) => return Box::new(future::err(err)),
// Make sure we check domain and mode first. URL must be valid.
let mode = match url_mode(&request.url) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the body of client_async_tls().

Ok(m) => m,
Err(e) => return Box::new(future::err(e.into())),
};
let domain = match request.url.host_str() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a function which already does the same, it's called domain() and it has been used before, what was the reason to not using it?

Some(d) => d.to_string(),
None => return Box::new(future::err(Error::Url("No host name in the URL".into()))),
};
let port = request.url.port_or_known_default().expect("Bug: port unknown");

Box::new(tcp_connect((domain.as_str(), port), handle).map_err(|e| e.into())
.and_then(move |socket| client_async_tls(request, socket)))
}
if dangerously {
Box::new(tcp_connect((domain.as_str(), port), handle).map_err(|e| e.into())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the body of client_async_tls().

.and_then(move |socket| danger_wrap_stream(socket, mode))
.and_then(|mut stream| {
NoDelay::set_nodelay(&mut stream, true)
.map(move |()| stream)
.map_err(|e| e.into())
})
.and_then(move |stream| client_async(request, stream)))
} else {
Box::new(tcp_connect((domain.as_str(), port), handle).map_err(|e| e.into())
.and_then(move |socket| client_async_tls(request, socket)))
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use tungstenite::error::Error as WsError;
use tungstenite::server;

#[cfg(feature="connect")]
pub use connect::{connect_async, client_async_tls};
pub use connect::{connect_async, client_async_tls, danger_connect_async};

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
Expand Down