Skip to content

Commit 6a47eaf

Browse files
authored
Merge pull request #218 from wiomoc/master
Adding native_tls support
2 parents 66de29a + 893094a commit 6a47eaf

File tree

9 files changed

+181
-54
lines changed

9 files changed

+181
-54
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ version = "1.0.18"
3939
optional = true
4040
version = "0.9"
4141

42+
[dependencies.native-tls]
43+
optional = true
44+
version = "0.1.5"
45+
4246
[dev-dependencies]
4347
clap = "2.31.2"
4448
env_logger = "0.5.6"
@@ -52,3 +56,4 @@ permessage-deflate = [
5256
"libc",
5357
]
5458
ssl = ["openssl"]
59+
nativetls = ["native-tls"]

src/connection.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use url;
1212

1313
#[cfg(feature = "ssl")]
1414
use openssl::ssl::HandshakeError;
15+
#[cfg(feature = "nativetls")]
16+
use native_tls::HandshakeError;
1517

1618
use frame::Frame;
1719
use handler::Handler;
@@ -146,7 +148,7 @@ where
146148
}
147149
}
148150

149-
#[cfg(feature = "ssl")]
151+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
150152
pub fn encrypt(&mut self) -> Result<()> {
151153
let sock = self.socket().try_clone()?;
152154
let ssl_stream = match self.endpoint {
@@ -159,6 +161,7 @@ where
159161
self.socket = Stream::tls_live(stream);
160162
Ok(())
161163
}
164+
#[cfg(feature = "ssl")]
162165
Err(Error {
163166
kind: Kind::SslHandshake(handshake_err),
164167
details,
@@ -171,6 +174,19 @@ where
171174
Ok(())
172175
}
173176
},
177+
#[cfg(feature = "nativetls")]
178+
Err(Error {
179+
kind: Kind::SslHandshake(handshake_err),
180+
details,
181+
}) => match handshake_err {
182+
HandshakeError::Failure(_) => {
183+
Err(Error::new(Kind::SslHandshake(handshake_err), details))
184+
}
185+
HandshakeError::Interrupted(mid) => {
186+
self.socket = Stream::tls(mid);
187+
Ok(())
188+
}
189+
},
174190
Err(e) => Err(e),
175191
}
176192
}
@@ -196,7 +212,7 @@ where
196212
}
197213

198214
// Resetting may be necessary in order to try all possible addresses for a server
199-
#[cfg(feature = "ssl")]
215+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
200216
pub fn reset(&mut self) -> Result<()> {
201217
// if self.is_client() {
202218
if let Client(ref url) = self.endpoint {
@@ -215,6 +231,7 @@ where
215231
self.socket = Stream::tls_live(stream);
216232
Ok(())
217233
}
234+
#[cfg(feature = "ssl")]
218235
Err(Error {
219236
kind: Kind::SslHandshake(handshake_err),
220237
details,
@@ -227,6 +244,19 @@ where
227244
Ok(())
228245
}
229246
},
247+
#[cfg(feature = "nativetls")]
248+
Err(Error {
249+
kind: Kind::SslHandshake(handshake_err),
250+
details,
251+
}) => match handshake_err {
252+
HandshakeError::Failure(_) => {
253+
Err(Error::new(Kind::SslHandshake(handshake_err), details))
254+
}
255+
HandshakeError::Interrupted(mid) => {
256+
self.socket = Stream::tls(mid);
257+
Ok(())
258+
}
259+
},
230260
Err(e) => Err(e),
231261
}
232262
} else {
@@ -253,7 +283,7 @@ where
253283
}
254284
}
255285

256-
#[cfg(not(feature = "ssl"))]
286+
#[cfg(not(any(feature = "ssl", feature = "nativetls")))]
257287
pub fn reset(&mut self) -> Result<()> {
258288
if self.is_client() {
259289
if let Connecting(ref mut req, ref mut res) = self.state {

src/deflate/extension.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::mem::replace;
22

33
#[cfg(feature = "ssl")]
44
use openssl::ssl::SslStream;
5+
#[cfg(feature = "nativetls")]
6+
use native_tls::TlsStream as SslStream;
57
use url;
68

79
use frame::Frame;
@@ -10,7 +12,7 @@ use handshake::{Handshake, Request, Response};
1012
use message::Message;
1113
use protocol::{CloseCode, OpCode};
1214
use result::{Error, Kind, Result};
13-
#[cfg(feature = "ssl")]
15+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
1416
use util::TcpStream;
1517
use util::{Timeout, Token};
1618

@@ -546,7 +548,7 @@ impl<H: Handler> Handler for DeflateHandler<H> {
546548
}
547549

548550
#[inline]
549-
#[cfg(feature = "ssl")]
551+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
550552
fn upgrade_ssl_client(
551553
&mut self,
552554
stream: TcpStream,
@@ -556,7 +558,7 @@ impl<H: Handler> Handler for DeflateHandler<H> {
556558
}
557559

558560
#[inline]
559-
#[cfg(feature = "ssl")]
561+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
560562
fn upgrade_ssl_server(&mut self, stream: TcpStream) -> Result<SslStream<TcpStream>> {
561563
self.inner.upgrade_ssl_server(stream)
562564
}

src/handler.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use log::Level::Error as ErrorLevel;
22
#[cfg(feature = "ssl")]
33
use openssl::ssl::{SslConnectorBuilder, SslMethod, SslStream};
4+
#[cfg(feature = "nativetls")]
5+
use native_tls::{TlsConnector, TlsStream as SslStream};
46
use url;
57

68
use frame::Frame;
@@ -10,7 +12,7 @@ use protocol::CloseCode;
1012
use result::{Error, Kind, Result};
1113
use util::{Timeout, Token};
1214

13-
#[cfg(feature = "ssl")]
15+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
1416
use util::TcpStream;
1517

1618
/// The core trait of this library.
@@ -304,12 +306,32 @@ pub trait Handler {
304306
connector.connect(domain, stream).map_err(Error::from)
305307
}
306308

309+
#[inline]
310+
#[cfg(feature = "nativetls")]
311+
fn upgrade_ssl_client(
312+
&mut self,
313+
stream: TcpStream,
314+
url: &url::Url,
315+
) -> Result<SslStream<TcpStream>> {
316+
let domain = url.domain().ok_or(Error::new(
317+
Kind::Protocol,
318+
format!("Unable to parse domain from {}. Needed for SSL.", url),
319+
))?;
320+
let connector = TlsConnector::builder().and_then(|builder| builder.build())
321+
.map_err(|e| {
322+
Error::new(
323+
Kind::Internal,
324+
format!("Failed to upgrade client to SSL: {}", e),
325+
)
326+
})?;
327+
connector.connect(domain, stream).map_err(Error::from)
328+
}
307329
/// A method for wrapping a server TcpStream with Ssl Authentication machinery
308330
///
309331
/// Override this method to customize how the connection is encrypted. By default
310332
/// this method is not implemented.
311333
#[inline]
312-
#[cfg(feature = "ssl")]
334+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
313335
fn upgrade_ssl_server(&mut self, _: TcpStream) -> Result<SslStream<TcpStream>> {
314336
unimplemented!()
315337
}

src/io.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use url::Url;
1313

1414
#[cfg(feature = "ssl")]
1515
use openssl::ssl::Error as SslError;
16+
#[cfg(feature = "native_tls")]
17+
use native_tls::Error as SslError;
1618

1719
use super::Settings;
1820
use communication::{Command, Sender, Signal};
@@ -142,7 +144,7 @@ where
142144
}
143145
}
144146

145-
#[cfg(feature = "ssl")]
147+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
146148
pub fn connect(&mut self, poll: &mut Poll, url: Url) -> Result<()> {
147149
let settings = self.settings;
148150

@@ -211,6 +213,7 @@ where
211213
if will_encrypt {
212214
while let Err(ssl_error) = self.connections[tok.into()].encrypt() {
213215
match ssl_error.kind {
216+
#[cfg(feature = "ssl")]
214217
Kind::Ssl(SslError::Stream(ref io_error)) => {
215218
if let Some(errno) = io_error.raw_os_error() {
216219
if errno == CONNECTION_REFUSED {
@@ -225,6 +228,17 @@ where
225228
}
226229
}
227230
}
231+
#[cfg(feature = "nativetls")]
232+
Kind::Ssl(_) => {
233+
if let Err(reset_error) = self.connections[tok.into()].reset() {
234+
trace!(
235+
"Encountered error while trying to reset connection: {:?}",
236+
reset_error
237+
);
238+
} else {
239+
continue;
240+
}
241+
}
228242
_ => (),
229243
}
230244
self.connections[tok.into()].error(ssl_error);
@@ -250,7 +264,7 @@ where
250264
})
251265
}
252266

253-
#[cfg(not(feature = "ssl"))]
267+
#[cfg(not(any(feature = "ssl", feature = "nativetls")))]
254268
pub fn connect(&mut self, poll: &mut Poll, url: Url) -> Result<()> {
255269
let settings = self.settings;
256270

@@ -340,7 +354,7 @@ where
340354
})
341355
}
342356

343-
#[cfg(feature = "ssl")]
357+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
344358
pub fn accept(&mut self, poll: &mut Poll, sock: TcpStream) -> Result<()> {
345359
let factory = &mut self.factory;
346360
let settings = self.settings;
@@ -396,7 +410,7 @@ where
396410
})
397411
}
398412

399-
#[cfg(not(feature = "ssl"))]
413+
#[cfg(not(any(feature = "ssl", feature = "nativetls")))]
400414
pub fn accept(&mut self, poll: &mut Poll, sock: TcpStream) -> Result<()> {
401415
let factory = &mut self.factory;
402416
let settings = self.settings;

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ extern crate mio;
1010
extern crate mio_extras;
1111
#[cfg(feature = "ssl")]
1212
extern crate openssl;
13+
#[cfg(feature = "nativetls")]
14+
extern crate native_tls;
1315
extern crate rand;
1416
extern crate sha1;
1517
extern crate slab;

src/result.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use httparse;
1010
use mio;
1111
#[cfg(feature = "ssl")]
1212
use openssl::ssl::{Error as SslError, HandshakeError as SslHandshakeError};
13-
#[cfg(feature = "ssl")]
13+
#[cfg(feature = "nativetls")]
14+
use native_tls::{Error as SslError, HandshakeError as SslHandshakeError};
15+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
1416
type HandshakeError = SslHandshakeError<mio::tcp::TcpStream>;
1517

1618
use communication::Command;
@@ -51,10 +53,10 @@ pub enum Kind {
5153
/// the queue may relieve the situation.
5254
Queue(mio::channel::SendError<Command>),
5355
/// Indicates a failure to perform SSL encryption.
54-
#[cfg(feature = "ssl")]
56+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
5557
Ssl(SslError),
5658
/// Indicates a failure to perform SSL encryption.
57-
#[cfg(feature = "ssl")]
59+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
5860
SslHandshake(HandshakeError),
5961
/// A custom error kind for use by applications. This error kind involves extra overhead
6062
/// because it will allocate the memory on the heap. The WebSocket ignores such errors by
@@ -116,9 +118,9 @@ impl StdError for Error {
116118
Kind::Encoding(ref err) => err.description(),
117119
Kind::Io(ref err) => err.description(),
118120
Kind::Http(_) => "Unable to parse HTTP",
119-
#[cfg(feature = "ssl")]
121+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
120122
Kind::Ssl(ref err) => err.description(),
121-
#[cfg(feature = "ssl")]
123+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
122124
Kind::SslHandshake(ref err) => err.description(),
123125
Kind::Queue(_) => "Unable to send signal on event loop",
124126
Kind::Custom(ref err) => err.description(),
@@ -129,9 +131,9 @@ impl StdError for Error {
129131
match self.kind {
130132
Kind::Encoding(ref err) => Some(err),
131133
Kind::Io(ref err) => Some(err),
132-
#[cfg(feature = "ssl")]
134+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
133135
Kind::Ssl(ref err) => Some(err),
134-
#[cfg(feature = "ssl")]
136+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
135137
Kind::SslHandshake(ref err) => err.cause(),
136138
Kind::Custom(ref err) => Some(err.as_ref()),
137139
_ => None,
@@ -178,14 +180,14 @@ impl From<Utf8Error> for Error {
178180
}
179181
}
180182

181-
#[cfg(feature = "ssl")]
183+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
182184
impl From<SslError> for Error {
183185
fn from(err: SslError) -> Error {
184186
Error::new(Kind::Ssl(err), "")
185187
}
186188
}
187189

188-
#[cfg(feature = "ssl")]
190+
#[cfg(any(feature = "ssl", feature = "nativetls"))]
189191
impl From<HandshakeError> for Error {
190192
fn from(err: HandshakeError) -> Error {
191193
Error::new(Kind::SslHandshake(err), "")

0 commit comments

Comments
 (0)