diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/msg.fbs | 6 | ||||
-rw-r--r-- | src/ops.rs | 35 | ||||
-rw-r--r-- | src/resources.rs | 18 |
3 files changed, 56 insertions, 3 deletions
diff --git a/src/msg.fbs b/src/msg.fbs index 9479d7892..16d10cdff 100644 --- a/src/msg.fbs +++ b/src/msg.fbs @@ -35,6 +35,7 @@ union Any { Write, WriteRes, Close, + Shutdown, Listen, ListenRes, Accept, @@ -290,6 +291,11 @@ table Close { rid: int; } +table Shutdown { + rid: int; + how: uint; +} + table Listen { network: string; address: string; diff --git a/src/ops.rs b/src/ops.rs index 53163dfd4..fb67d4bef 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -9,6 +9,8 @@ use isolate::Isolate; use isolate::IsolateState; use isolate::Op; use msg; +use resources; +use resources::Resource; use tokio_util; use flatbuffers::FlatBufferBuilder; @@ -19,10 +21,9 @@ use hyper; use hyper::rt::{Future, Stream}; use hyper::Client; use remove_dir_all::remove_dir_all; -use resources; use std; use std::fs; -use std::net::SocketAddr; +use std::net::{Shutdown, SocketAddr}; #[cfg(any(unix))] use std::os::unix::fs::PermissionsExt; use std::path::Path; @@ -84,6 +85,7 @@ pub fn dispatch( msg::Any::Read => op_read, msg::Any::Write => op_write, msg::Any::Close => op_close, + msg::Any::Shutdown => op_shutdown, msg::Any::Remove => op_remove, msg::Any::ReadFile => op_read_file, msg::Any::ReadDir => op_read_dir, @@ -614,6 +616,35 @@ fn op_close( } } +fn op_shutdown( + _state: Arc<IsolateState>, + base: &msg::Base, + data: &'static mut [u8], +) -> Box<Op> { + assert_eq!(data.len(), 0); + let inner = base.inner_as_shutdown().unwrap(); + let rid = inner.rid(); + let how = inner.how(); + match resources::lookup(rid) { + None => odd_future(errors::new( + errors::ErrorKind::BadFileDescriptor, + String::from("Bad File Descriptor"), + )), + Some(mut resource) => { + let shutdown_mode = match how { + 0 => Shutdown::Read, + 1 => Shutdown::Write, + _ => unimplemented!(), + }; + blocking!(base.sync(), || { + // Use UFCS for disambiguation + Resource::shutdown(&mut resource, shutdown_mode)?; + Ok(empty_buf()) + }) + } + } +} + fn op_read( _state: Arc<IsolateState>, base: &msg::Base, diff --git a/src/resources.rs b/src/resources.rs index 75bad04b7..5a13e6cbf 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -8,13 +8,15 @@ // descriptors". This module implements a global resource table. Ops (AKA // handlers) look up resources by their integer id here. +use errors::DenoError; + use futures; use futures::Poll; use std; use std::collections::HashMap; use std::io::Error; use std::io::{Read, Write}; -use std::net::SocketAddr; +use std::net::{Shutdown, SocketAddr}; use std::sync::atomic::AtomicIsize; use std::sync::atomic::Ordering; use std::sync::Mutex; @@ -79,6 +81,20 @@ impl Resource { let r = table.remove(&self.rid); assert!(r.is_some()); } + + pub fn shutdown(&mut self, how: Shutdown) -> Result<(), DenoError> { + let mut table = RESOURCE_TABLE.lock().unwrap(); + let maybe_repr = table.get_mut(&self.rid); + match maybe_repr { + None => panic!("bad rid"), + Some(repr) => match repr { + Repr::TcpStream(ref mut f) => { + TcpStream::shutdown(f, how).map_err(|err| DenoError::from(err)) + } + _ => panic!("Cannot shutdown"), + }, + } + } } impl Read for Resource { |