summaryrefslogtreecommitdiff
path: root/cli/ops/net.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/ops/net.rs')
-rw-r--r--cli/ops/net.rs151
1 files changed, 151 insertions, 0 deletions
diff --git a/cli/ops/net.rs b/cli/ops/net.rs
new file mode 100644
index 000000000..507eff504
--- /dev/null
+++ b/cli/ops/net.rs
@@ -0,0 +1,151 @@
+// 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::resources::Resource;
+use crate::state::ThreadSafeState;
+use crate::tokio_util;
+use deno::*;
+use futures::Future;
+use std;
+use std::convert::From;
+use std::net::Shutdown;
+use tokio;
+use tokio::net::TcpListener;
+use tokio::net::TcpStream;
+
+#[derive(Deserialize)]
+struct AcceptArgs {
+ rid: i32,
+}
+
+pub fn op_accept(
+ _state: &ThreadSafeState,
+ args: Value,
+ _zero_copy: Option<PinnedBuf>,
+) -> Result<JsonOp, ErrBox> {
+ let args: AcceptArgs = serde_json::from_value(args)?;
+ let server_rid = args.rid as u32;
+
+ let server_resource = resources::lookup(server_rid)?;
+ let op = tokio_util::accept(server_resource)
+ .and_then(move |(tcp_stream, _socket_addr)| {
+ let local_addr = tcp_stream.local_addr()?;
+ let remote_addr = tcp_stream.peer_addr()?;
+ let tcp_stream_resource = resources::add_tcp_stream(tcp_stream);
+ Ok((tcp_stream_resource, local_addr, remote_addr))
+ })
+ .map_err(ErrBox::from)
+ .and_then(move |(tcp_stream_resource, local_addr, remote_addr)| {
+ futures::future::ok(json!({
+ "rid": tcp_stream_resource.rid,
+ "localAddr": local_addr.to_string(),
+ "remoteAddr": remote_addr.to_string(),
+ }))
+ });
+
+ Ok(JsonOp::Async(Box::new(op)))
+}
+
+#[derive(Deserialize)]
+struct DialArgs {
+ transport: String,
+ hostname: String,
+ port: u16,
+}
+
+pub fn op_dial(
+ state: &ThreadSafeState,
+ args: Value,
+ _zero_copy: Option<PinnedBuf>,
+) -> Result<JsonOp, ErrBox> {
+ let args: DialArgs = serde_json::from_value(args)?;
+ assert_eq!(args.transport, "tcp"); // TODO Support others.
+
+ // 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 op = resolve_addr(&address).and_then(move |addr| {
+ TcpStream::connect(&addr)
+ .map_err(ErrBox::from)
+ .and_then(move |tcp_stream| {
+ let local_addr = tcp_stream.local_addr()?;
+ let remote_addr = tcp_stream.peer_addr()?;
+ let tcp_stream_resource = resources::add_tcp_stream(tcp_stream);
+ Ok((tcp_stream_resource, local_addr, remote_addr))
+ })
+ .map_err(ErrBox::from)
+ .and_then(move |(tcp_stream_resource, local_addr, remote_addr)| {
+ futures::future::ok(json!({
+ "rid": tcp_stream_resource.rid,
+ "localAddr": local_addr.to_string(),
+ "remoteAddr": remote_addr.to_string(),
+ }))
+ })
+ });
+
+ Ok(JsonOp::Async(Box::new(op)))
+}
+
+#[derive(Deserialize)]
+struct ShutdownArgs {
+ rid: i32,
+ how: i32,
+}
+
+pub fn op_shutdown(
+ _state: &ThreadSafeState,
+ args: Value,
+ _zero_copy: Option<PinnedBuf>,
+) -> Result<JsonOp, ErrBox> {
+ let args: ShutdownArgs = serde_json::from_value(args)?;
+
+ let rid = args.rid as u32;
+ let how = args.how;
+ let mut resource = resources::lookup(rid)?;
+
+ let shutdown_mode = match how {
+ 0 => Shutdown::Read,
+ 1 => Shutdown::Write,
+ _ => unimplemented!(),
+ };
+
+ // Use UFCS for disambiguation
+ Resource::shutdown(&mut resource, shutdown_mode)?;
+ Ok(JsonOp::Sync(json!({})))
+}
+
+#[derive(Deserialize)]
+struct ListenArgs {
+ transport: String,
+ hostname: String,
+ port: u16,
+}
+
+pub fn op_listen(
+ state: &ThreadSafeState,
+ args: Value,
+ _zero_copy: Option<PinnedBuf>,
+) -> Result<JsonOp, ErrBox> {
+ let args: ListenArgs = serde_json::from_value(args)?;
+ assert_eq!(args.transport, "tcp");
+
+ // 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 addr = resolve_addr(&address).wait()?;
+ let listener = TcpListener::bind(&addr)?;
+ let local_addr = listener.local_addr()?;
+ let resource = resources::add_tcp_listener(listener);
+
+ Ok(JsonOp::Sync(json!({
+ "rid": resource.rid,
+ "localAddr": local_addr.to_string()
+ })))
+}