connect TLS aftet tunneling to a proxy
This commit is contained in:
		| @@ -16,12 +16,13 @@ hyper = "0.11" | |||||||
| hyper-tls = "0.1.2" | hyper-tls = "0.1.2" | ||||||
| libflate = "0.1.5" | libflate = "0.1.5" | ||||||
| log = "0.3" | log = "0.3" | ||||||
| native-tls = "0.1" | native-tls = "0.1.3" | ||||||
| serde = "1.0" | serde = "1.0" | ||||||
| serde_json = "1.0" | serde_json = "1.0" | ||||||
| serde_urlencoded = "0.5" | serde_urlencoded = "0.5" | ||||||
| tokio-core = "0.1.6" | tokio-core = "0.1.6" | ||||||
| tokio-io = "0.1" | tokio-io = "0.1" | ||||||
|  | tokio-tls = "0.1" | ||||||
| url = "1.2" | url = "1.2" | ||||||
|  |  | ||||||
| [dev-dependencies] | [dev-dependencies] | ||||||
|   | |||||||
| @@ -1,13 +1,14 @@ | |||||||
| use bytes::{BufMut, IntoBuf}; | use bytes::{Buf, BufMut, IntoBuf}; | ||||||
| use futures::{Async, Future, Poll}; | use futures::{Async, Future, Poll}; | ||||||
| use hyper::client::{HttpConnector, Service}; | use hyper::client::{HttpConnector, Service}; | ||||||
| use hyper::Uri; | use hyper::Uri; | ||||||
| use hyper_tls::{/*HttpsConnecting,*/ HttpsConnector, MaybeHttpsStream}; | use hyper_tls::{HttpsConnector, MaybeHttpsStream}; | ||||||
| use native_tls::TlsConnector; | use native_tls::TlsConnector; | ||||||
| use tokio_core::reactor::Handle; | use tokio_core::reactor::Handle; | ||||||
| use tokio_io::{AsyncRead, AsyncWrite}; | use tokio_io::{AsyncRead, AsyncWrite}; | ||||||
|  | use tokio_tls::{TlsConnectorExt, TlsStream}; | ||||||
|  |  | ||||||
| use std::io::{self, Cursor}; | use std::io::{self, Cursor, Read, Write}; | ||||||
| use std::sync::Arc; | use std::sync::Arc; | ||||||
|  |  | ||||||
| use {proxy, Proxy}; | use {proxy, Proxy}; | ||||||
| @@ -17,17 +18,19 @@ use {proxy, Proxy}; | |||||||
| pub struct Connector { | pub struct Connector { | ||||||
|     https: HttpsConnector<HttpConnector>, |     https: HttpsConnector<HttpConnector>, | ||||||
|     proxies: Arc<Vec<Proxy>>, |     proxies: Arc<Vec<Proxy>>, | ||||||
|  |     tls: TlsConnector, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Connector { | impl Connector { | ||||||
|     pub fn new(tls: TlsConnector, proxies: Arc<Vec<Proxy>>, handle: &Handle) -> Connector { |     pub fn new(tls: TlsConnector, proxies: Arc<Vec<Proxy>>, handle: &Handle) -> Connector { | ||||||
|         let mut http = HttpConnector::new(4, handle); |         let mut http = HttpConnector::new(4, handle); | ||||||
|         http.enforce_http(false); |         http.enforce_http(false); | ||||||
|         let https = HttpsConnector::from((http, tls)); |         let https = HttpsConnector::from((http, tls.clone())); | ||||||
|  |  | ||||||
|         Connector { |         Connector { | ||||||
|             https: https, |             https: https, | ||||||
|             proxies: proxies, |             proxies: proxies, | ||||||
|  |             tls: tls, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -47,20 +50,93 @@ impl Service for Connector { | |||||||
|             if let Some(puri) = proxy::proxies(prox, &uri) { |             if let Some(puri) = proxy::proxies(prox, &uri) { | ||||||
|                 if uri.scheme() == Some("https") { |                 if uri.scheme() == Some("https") { | ||||||
|                     let host = uri.authority().unwrap().to_owned(); |                     let host = uri.authority().unwrap().to_owned(); | ||||||
|                     return Box::new(self.https.call(puri).and_then(|conn| { |                     let tls = self.tls.clone(); | ||||||
|                         tunnel(conn, host) |                     return Box::new(self.https.call(puri).and_then(move |conn| { | ||||||
|  |                         tunnel(conn, host.clone()) | ||||||
|  |                             .and_then(move |tunneled| { | ||||||
|  |                                 tls.connect_async(&host, tunneled) | ||||||
|  |                                     .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) | ||||||
|  |                             }) | ||||||
|  |                             .map(|io| Conn::Proxied(io)) | ||||||
|                     })); |                     })); | ||||||
|                 } |                 } | ||||||
|                 return Box::new(self.https.call(puri)); |                 return Box::new(self.https.call(puri).map(|io| Conn::Normal(io))); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         Box::new(self.https.call(uri)) |         Box::new(self.https.call(uri).map(|io| Conn::Normal(io))) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub type Conn = MaybeHttpsStream<<HttpConnector as Service>::Response>; | type HttpStream = <HttpConnector as Service>::Response; | ||||||
|  | type HttpsStream = MaybeHttpsStream<HttpStream>; | ||||||
|  |  | ||||||
| pub type Connecting = Box<Future<Item=Conn, Error=io::Error>>; | pub type Connecting = Box<Future<Item=Conn, Error=io::Error>>; | ||||||
|  |  | ||||||
|  | pub enum Conn { | ||||||
|  |     Normal(HttpsStream), | ||||||
|  |     Proxied(TlsStream<MaybeHttpsStream<HttpStream>>), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Read for Conn { | ||||||
|  |     #[inline] | ||||||
|  |     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref mut s) => s.read(buf), | ||||||
|  |             Conn::Proxied(ref mut s) => s.read(buf), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Write for Conn { | ||||||
|  |     #[inline] | ||||||
|  |     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref mut s) => s.write(buf), | ||||||
|  |             Conn::Proxied(ref mut s) => s.write(buf), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[inline] | ||||||
|  |     fn flush(&mut self) -> io::Result<()> { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref mut s) => s.flush(), | ||||||
|  |             Conn::Proxied(ref mut s) => s.flush(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl AsyncRead for Conn { | ||||||
|  |     unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref s) => s.prepare_uninitialized_buffer(buf), | ||||||
|  |             Conn::Proxied(ref s) => s.prepare_uninitialized_buffer(buf), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref mut s) => s.read_buf(buf), | ||||||
|  |             Conn::Proxied(ref mut s) => s.read_buf(buf), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl AsyncWrite for Conn { | ||||||
|  |     fn shutdown(&mut self) -> Poll<(), io::Error> { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref mut s) => s.shutdown(), | ||||||
|  |             Conn::Proxied(ref mut s) => s.shutdown(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||||
|  |         match *self { | ||||||
|  |             Conn::Normal(ref mut s) => s.write_buf(buf), | ||||||
|  |             Conn::Proxied(ref mut s) => s.write_buf(buf), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| fn tunnel<T>(conn: T, host: String) -> Tunnel<T> { | fn tunnel<T>(conn: T, host: String) -> Tunnel<T> { | ||||||
|      let buf = format!("\ |      let buf = format!("\ | ||||||
|         CONNECT {0} HTTP/1.1\r\n\ |         CONNECT {0} HTTP/1.1\r\n\ | ||||||
|   | |||||||
| @@ -132,6 +132,7 @@ extern crate serde_json; | |||||||
| extern crate serde_urlencoded; | extern crate serde_urlencoded; | ||||||
| extern crate tokio_core; | extern crate tokio_core; | ||||||
| extern crate tokio_io; | extern crate tokio_io; | ||||||
|  | extern crate tokio_tls; | ||||||
| extern crate url; | extern crate url; | ||||||
|  |  | ||||||
| pub use hyper::header; | pub use hyper::header; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user