summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorJonathon Orsi <jonathon.orsi@gmail.com>2019-09-23 14:40:38 -0400
committerRyan Dahl <ry@tinyclouds.org>2019-09-23 15:12:42 -0400
commit045e74bb39d7743b774cfd2b889bc6ce1e1ad245 (patch)
tree93a8429860a40eabaee813e6f983f64aebd8afc7 /cli
parent4ff04ad96f27b7073e3478630ed249eedc76af2b (diff)
feat: Add Deno.dialTLS()
Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
Diffstat (limited to 'cli')
-rw-r--r--cli/Cargo.toml2
-rw-r--r--cli/ops/mod.rs5
-rw-r--r--cli/ops/tls.rs76
-rw-r--r--cli/resources.rs13
4 files changed, 96 insertions, 0 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index b9a9c1456..463c9fbc1 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -56,6 +56,8 @@ tokio-rustls = "0.10.0"
tokio-threadpool = "0.1.15"
url = "1.7.2"
utime = "0.2.1"
+webpki = "0.21.0"
+webpki-roots = "0.17.0"
[target.'cfg(windows)'.dependencies]
winapi = "0.3.8"
diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs
index 7a2e9c9f4..ea71fee9f 100644
--- a/cli/ops/mod.rs
+++ b/cli/ops/mod.rs
@@ -20,6 +20,7 @@ mod random;
mod repl;
mod resources;
mod timers;
+mod tls;
mod workers;
// Warning! These values are duplicated in the TypeScript code (js/dispatch.ts),
@@ -81,6 +82,7 @@ pub const OP_TRUNCATE: OpId = 54;
pub const OP_MAKE_TEMP_DIR: OpId = 55;
pub const OP_CWD: OpId = 56;
pub const OP_FETCH_ASSET: OpId = 57;
+pub const OP_DIAL_TLS: OpId = 58;
pub fn dispatch(
state: &ThreadSafeState,
@@ -300,6 +302,9 @@ pub fn dispatch(
control,
zero_copy,
),
+ OP_DIAL_TLS => {
+ dispatch_json::dispatch(tls::op_dial_tls, state, control, zero_copy)
+ }
_ => panic!("bad op_id"),
};
diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs
new file mode 100644
index 000000000..2b1d94f2b
--- /dev/null
+++ b/cli/ops/tls.rs
@@ -0,0 +1,76 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+use super::dispatch_json::{Deserialize, JsonOp, Value};
+use crate::resolve_addr::resolve_addr;
+use crate::resources;
+use crate::state::ThreadSafeState;
+use deno::*;
+use futures::Future;
+use std;
+use std::convert::From;
+use std::sync::Arc;
+use tokio;
+use tokio::net::TcpStream;
+use tokio_rustls::{rustls::ClientConfig, TlsConnector};
+use webpki;
+use webpki::DNSNameRef;
+use webpki_roots;
+
+#[derive(Deserialize)]
+struct DialTLSArgs {
+ hostname: String,
+ port: u16,
+}
+
+pub fn op_dial_tls(
+ state: &ThreadSafeState,
+ args: Value,
+ _zero_copy: Option<PinnedBuf>,
+) -> Result<JsonOp, ErrBox> {
+ let args: DialTLSArgs = serde_json::from_value(args)?;
+
+ // TODO(ry) Using format! is suboptimal here. Better would be if
+ // state.check_net and resolve_addr() took hostname and port directly.
+ let address = format!("{}:{}", args.hostname, args.port);
+
+ state.check_net(&address)?;
+
+ let mut domain = args.hostname;
+ if domain.is_empty() {
+ domain.push_str("localhost");
+ }
+
+ let op = resolve_addr(&address).and_then(move |addr| {
+ TcpStream::connect(&addr)
+ .and_then(move |tcp_stream| {
+ let local_addr = tcp_stream.local_addr()?;
+ let remote_addr = tcp_stream.peer_addr()?;
+ let mut config = ClientConfig::new();
+ config
+ .root_store
+ .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
+
+ let tls_connector = TlsConnector::from(Arc::new(config));
+ Ok((tls_connector, tcp_stream, local_addr, remote_addr))
+ })
+ .map_err(ErrBox::from)
+ .and_then(
+ move |(tls_connector, tcp_stream, local_addr, remote_addr)| {
+ let dnsname = DNSNameRef::try_from_ascii_str(&domain)
+ .expect("Invalid DNS lookup");
+ tls_connector
+ .connect(dnsname, tcp_stream)
+ .map_err(ErrBox::from)
+ .and_then(move |tls_stream| {
+ let tls_stream_resource = resources::add_tls_stream(tls_stream);
+ futures::future::ok(json!({
+ "rid": tls_stream_resource.rid,
+ "localAddr": local_addr.to_string(),
+ "remoteAddr": remote_addr.to_string(),
+ }))
+ })
+ },
+ )
+ });
+
+ Ok(JsonOp::Async(Box::new(op)))
+}
diff --git a/cli/resources.rs b/cli/resources.rs
index 3bce51afb..0fdb0e182 100644
--- a/cli/resources.rs
+++ b/cli/resources.rs
@@ -36,6 +36,7 @@ use tokio::io::{AsyncRead, AsyncWrite};
use tokio::net::TcpStream;
use tokio::sync::mpsc;
use tokio_process;
+use tokio_rustls::client::TlsStream;
pub type ResourceId = u32; // Sometimes referred to RID.
@@ -89,6 +90,7 @@ enum Repr {
// See: https://github.com/tokio-rs/tokio/issues/846
TcpListener(tokio::net::TcpListener, Option<futures::task::Task>),
TcpStream(tokio::net::TcpStream),
+ TlsStream(Box<TlsStream<TcpStream>>),
HttpBody(HttpBody),
Repl(Arc<Mutex<Repl>>),
// Enum size is bounded by the largest variant.
@@ -134,6 +136,7 @@ fn inspect_repr(repr: &Repr) -> String {
Repr::FsFile(_) => "fsFile",
Repr::TcpListener(_, _) => "tcpListener",
Repr::TcpStream(_) => "tcpStream",
+ Repr::TlsStream(_) => "tlsStream",
Repr::HttpBody(_) => "httpBody",
Repr::Repl(_) => "repl",
Repr::Child(_) => "child",
@@ -249,6 +252,7 @@ impl DenoAsyncRead for Resource {
Repr::FsFile(ref mut f) => f.poll_read(buf),
Repr::Stdin(ref mut f) => f.poll_read(buf),
Repr::TcpStream(ref mut f) => f.poll_read(buf),
+ Repr::TlsStream(ref mut f) => f.poll_read(buf),
Repr::HttpBody(ref mut f) => f.poll_read(buf),
Repr::ChildStdout(ref mut f) => f.poll_read(buf),
Repr::ChildStderr(ref mut f) => f.poll_read(buf),
@@ -289,6 +293,7 @@ impl DenoAsyncWrite for Resource {
Repr::Stdout(ref mut f) => f.poll_write(buf),
Repr::Stderr(ref mut f) => f.poll_write(buf),
Repr::TcpStream(ref mut f) => f.poll_write(buf),
+ Repr::TlsStream(ref mut f) => f.poll_write(buf),
Repr::ChildStdin(ref mut f) => f.poll_write(buf),
_ => {
return Err(bad_resource());
@@ -332,6 +337,14 @@ pub fn add_tcp_stream(stream: tokio::net::TcpStream) -> Resource {
Resource { rid }
}
+pub fn add_tls_stream(stream: TlsStream<TcpStream>) -> Resource {
+ let rid = new_rid();
+ let mut tg = RESOURCE_TABLE.lock().unwrap();
+ let r = tg.insert(rid, Repr::TlsStream(Box::new(stream)));
+ assert!(r.is_none());
+ Resource { rid }
+}
+
pub fn add_reqwest_body(body: ReqwestDecoder) -> Resource {
let rid = new_rid();
let mut tg = RESOURCE_TABLE.lock().unwrap();