summaryrefslogtreecommitdiff
path: root/cli/ops
diff options
context:
space:
mode:
Diffstat (limited to 'cli/ops')
-rw-r--r--cli/ops/io.rs8
-rw-r--r--cli/ops/net.rs10
-rw-r--r--cli/ops/tls.rs80
3 files changed, 89 insertions, 9 deletions
diff --git a/cli/ops/io.rs b/cli/ops/io.rs
index e045eddfb..9c228ffad 100644
--- a/cli/ops/io.rs
+++ b/cli/ops/io.rs
@@ -157,7 +157,7 @@ impl StreamResourceHolder {
pub enum StreamResource {
Stdin(tokio::io::Stdin, TTYMetadata),
FsFile(Option<(tokio::fs::File, FileMetadata)>),
- TcpStream(tokio::net::TcpStream),
+ TcpStream(Option<tokio::net::TcpStream>),
#[cfg(not(windows))]
UnixStream(tokio::net::UnixStream),
ServerTlsStream(Box<ServerTlsStream<TcpStream>>),
@@ -195,7 +195,7 @@ impl DenoAsyncRead for StreamResource {
FsFile(Some((f, _))) => f,
FsFile(None) => return Poll::Ready(Err(OpError::resource_unavailable())),
Stdin(f, _) => f,
- TcpStream(f) => f,
+ TcpStream(Some(f)) => f,
#[cfg(not(windows))]
UnixStream(f) => f,
ClientTlsStream(f) => f,
@@ -297,7 +297,7 @@ impl DenoAsyncWrite for StreamResource {
let f: &mut dyn UnpinAsyncWrite = match self {
FsFile(Some((f, _))) => f,
FsFile(None) => return Poll::Pending,
- TcpStream(f) => f,
+ TcpStream(Some(f)) => f,
#[cfg(not(windows))]
UnixStream(f) => f,
ClientTlsStream(f) => f,
@@ -315,7 +315,7 @@ impl DenoAsyncWrite for StreamResource {
let f: &mut dyn UnpinAsyncWrite = match self {
FsFile(Some((f, _))) => f,
FsFile(None) => return Poll::Pending,
- TcpStream(f) => f,
+ TcpStream(Some(f)) => f,
#[cfg(not(windows))]
UnixStream(f) => f,
ClientTlsStream(f) => f,
diff --git a/cli/ops/net.rs b/cli/ops/net.rs
index 2636a2c2d..101fc5130 100644
--- a/cli/ops/net.rs
+++ b/cli/ops/net.rs
@@ -81,9 +81,9 @@ fn accept_tcp(
let mut state = state_.borrow_mut();
let rid = state.resource_table.add(
"tcpStream",
- Box::new(StreamResourceHolder::new(StreamResource::TcpStream(
+ Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some(
tcp_stream,
- ))),
+ )))),
);
Ok(json!({
"rid": rid,
@@ -280,9 +280,9 @@ fn op_connect(
let mut state = state_.borrow_mut();
let rid = state.resource_table.add(
"tcpStream",
- Box::new(StreamResourceHolder::new(StreamResource::TcpStream(
+ Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some(
tcp_stream,
- ))),
+ )))),
);
Ok(json!({
"rid": rid,
@@ -367,7 +367,7 @@ fn op_shutdown(
.get_mut::<StreamResourceHolder>(rid)
.ok_or_else(OpError::bad_resource_id)?;
match resource_holder.resource {
- StreamResource::TcpStream(ref mut stream) => {
+ StreamResource::TcpStream(Some(ref mut stream)) => {
TcpStream::shutdown(stream, shutdown_mode).map_err(OpError::from)?;
}
#[cfg(unix)]
diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs
index 60338f7fc..dca2d8012 100644
--- a/cli/ops/tls.rs
+++ b/cli/ops/tls.rs
@@ -28,6 +28,7 @@ use tokio_rustls::{
use webpki::DNSNameRef;
pub fn init(i: &mut Isolate, s: &State) {
+ i.register_op("op_start_tls", s.stateful_json_op(op_start_tls));
i.register_op("op_connect_tls", s.stateful_json_op(op_connect_tls));
i.register_op("op_listen_tls", s.stateful_json_op(op_listen_tls));
i.register_op("op_accept_tls", s.stateful_json_op(op_accept_tls));
@@ -42,6 +43,85 @@ struct ConnectTLSArgs {
cert_file: Option<String>,
}
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct StartTLSArgs {
+ rid: u32,
+ cert_file: Option<String>,
+ hostname: String,
+}
+
+pub fn op_start_tls(
+ state: &State,
+ args: Value,
+ _zero_copy: Option<ZeroCopyBuf>,
+) -> Result<JsonOp, OpError> {
+ let args: StartTLSArgs = serde_json::from_value(args)?;
+ let rid = args.rid as u32;
+ let cert_file = args.cert_file.clone();
+ let state_ = state.clone();
+
+ let mut domain = args.hostname;
+ if domain.is_empty() {
+ domain.push_str("localhost");
+ }
+
+ let op = async move {
+ let mut state = state_.borrow_mut();
+
+ let mut resource_holder =
+ match state.resource_table.remove::<StreamResourceHolder>(rid) {
+ Some(resource) => *resource,
+ None => return Err(OpError::bad_resource_id()),
+ };
+
+ if let StreamResource::TcpStream(ref mut tcp_stream) =
+ resource_holder.resource
+ {
+ let tcp_stream = tcp_stream.take().unwrap();
+ 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);
+ if let Some(path) = cert_file {
+ let key_file = File::open(path)?;
+ let reader = &mut BufReader::new(key_file);
+ config.root_store.add_pem_file(reader).unwrap();
+ }
+
+ let tls_connector = TlsConnector::from(Arc::new(config));
+ let dnsname =
+ DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
+ let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?;
+
+ let rid = state.resource_table.add(
+ "clientTlsStream",
+ Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
+ Box::new(tls_stream),
+ ))),
+ );
+ Ok(json!({
+ "rid": rid,
+ "localAddr": {
+ "hostname": local_addr.ip().to_string(),
+ "port": local_addr.port(),
+ "transport": "tcp",
+ },
+ "remoteAddr": {
+ "hostname": remote_addr.ip().to_string(),
+ "port": remote_addr.port(),
+ "transport": "tcp",
+ }
+ }))
+ } else {
+ Err(OpError::bad_resource_id())
+ }
+ };
+ Ok(JsonOp::Async(op.boxed_local()))
+}
+
pub fn op_connect_tls(
state: &State,
args: Value,