From 94fac87bc620370262439af23e27171d5302720d Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 31 May 2018 19:12:23 +0200 Subject: [PATCH] Convert into edge-triggered model --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/main.rs | 51 +++++++++++++++++++++++++------------------------ src/master.rs | 47 ++++++++++++++++++++++++++++----------------- src/pgrp.rs | 17 ++++++++++------- src/resource.rs | 9 +++++---- src/scheme.rs | 48 +++++++++++++++++++++++----------------------- src/slave.rs | 41 +++++++++++++++++++++++++++------------ src/termios.rs | 17 ++++++++++------- src/winsize.rs | 17 ++++++++++------- 10 files changed, 148 insertions(+), 109 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4fbd9724a..648075be4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,13 @@ name = "ptyd" version = "0.1.0" dependencies = [ - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -16,9 +16,9 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/Cargo.toml b/Cargo.toml index dde595c1c3..1e9a58f6ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,5 +3,5 @@ name = "ptyd" version = "0.1.0" [dependencies] -redox_syscall = "0.1" +redox_syscall = "0.1.40" redox_termios = "0.1" diff --git a/src/main.rs b/src/main.rs index 9cdeb66b0c..b18f4e2012 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,8 +7,7 @@ use std::fs::File; use std::io::{Read, Write}; use syscall::data::Packet; -use syscall::error::EWOULDBLOCK; -use syscall::scheme::SchemeMut; +use syscall::scheme::SchemeBlockMut; mod master; mod pgrp; @@ -34,42 +33,44 @@ fn main(){ let mut packet = Packet::default(); socket.read(&mut packet).expect("pty: failed to read events from pty scheme"); - let a = packet.a; - scheme.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { + if let Some(a) = scheme.handle(&mut packet) { packet.a = a; - todo.push(packet); - } else { socket.write(&packet).expect("pty: failed to write responses to pty scheme"); + } else { + todo.push(packet); } let mut i = 0; while i < todo.len() { - let a = todo[i].a; - scheme.handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - let packet = todo.remove(i); + if let Some(a) = scheme.handle(&mut todo[i]) { + let mut packet = todo.remove(i); + packet.a = a; socket.write(&packet).expect("pty: failed to write responses to pty scheme"); + } else { + i += 1; } } - for (id, handle) in scheme.handles.iter() { + for (id, handle) in scheme.handles.iter_mut() { if let Some(count) = handle.fevent_count() { - socket.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: count - }).expect("pty: failed to write event"); + post_fevent(&mut socket, *id, syscall::EVENT_READ, count); + } + if handle.fevent_writable() { + post_fevent(&mut socket, *id, syscall::EVENT_WRITE, 1); } } } } } +fn post_fevent(socket: &mut File, id: usize, flags: usize, count: usize) { + socket.write(&Packet { + id: 0, + pid: 0, + uid: 0, + gid: 0, + a: syscall::number::SYS_FEVENT, + b: id, + c: flags, + d: count + }).expect("pty: failed to write event"); +} diff --git a/src/master.rs b/src/master.rs index 7a356f4fe4..26ef5af60b 100644 --- a/src/master.rs +++ b/src/master.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::rc::{Rc, Weak}; -use syscall::error::{Error, Result, EINVAL, EWOULDBLOCK}; +use syscall::error::{Error, Result, EINVAL, EAGAIN}; use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; use pty::Pty; @@ -12,6 +12,8 @@ use resource::Resource; pub struct PtyMaster { pty: Rc>, flags: usize, + notified_read: bool, + notified_write: bool } impl PtyMaster { @@ -19,6 +21,8 @@ impl PtyMaster { PtyMaster { pty: pty, flags: flags, + notified_read: false, + notified_write: false } } } @@ -40,7 +44,7 @@ impl Resource for PtyMaster { self.pty.borrow_mut().path(buf) } - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result> { let mut pty = self.pty.borrow_mut(); if let Some(packet) = pty.miso.pop_front() { @@ -55,24 +59,24 @@ impl Resource for PtyMaster { pty.miso.push_front(packet[i..].to_vec()); } - Ok(i) + Ok(Some(i)) } else if self.flags & O_NONBLOCK == O_NONBLOCK || Rc::weak_count(&self.pty) == 0 { - Ok(0) + Err(Error::new(EAGAIN)) } else { - Err(Error::new(EWOULDBLOCK)) + Ok(None) } } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result> { let mut pty = self.pty.borrow_mut(); if pty.mosi.len() >= 64 { - return Err(Error::new(EWOULDBLOCK)); + return Ok(None); } pty.input(buf); - Ok(buf.len()) + Ok(Some(buf.len())) } fn sync(&self) -> Result { @@ -90,22 +94,29 @@ impl Resource for PtyMaster { } } - fn fevent(&self) -> Result<()> { + fn fevent(&mut self) -> Result<()> { + self.notified_read = false; // resend + self.notified_write = false; Ok(()) } - fn fevent_count(&self) -> Option { - { - let pty = self.pty.borrow(); - if let Some(data) = pty.miso.front() { - return Some(data.len()); + fn fevent_count(&mut self) -> Option { + let pty = self.pty.borrow(); + if let Some(data) = pty.miso.front() { + if !self.notified_read { + self.notified_read = true; + Some(data.len()) + } else { + None } - } - - if Rc::weak_count(&self.pty) == 0 { - Some(0) } else { + self.notified_read = false; None } } + fn fevent_writable(&mut self) -> bool { + let notified = self.notified_write; + self.notified_write = true; + !notified + } } diff --git a/src/pgrp.rs b/src/pgrp.rs index 56eb16ef9c..5ffc39089b 100644 --- a/src/pgrp.rs +++ b/src/pgrp.rs @@ -45,7 +45,7 @@ impl Resource for PtyPgrp { } } - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let pty = pty_lock.borrow(); let pgrp: &[u8] = unsafe { @@ -60,13 +60,13 @@ impl Resource for PtyPgrp { buf[i] = pgrp[i]; i += 1; } - Ok(i) + Ok(Some(i)) } else { - Ok(0) + Ok(Some(0)) } } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let mut pty = pty_lock.borrow_mut(); let pgrp: &mut [u8] = unsafe { @@ -81,7 +81,7 @@ impl Resource for PtyPgrp { pgrp[i] = buf[i]; i += 1; } - Ok(i) + Ok(Some(i)) } else { Err(Error::new(EPIPE)) } @@ -102,11 +102,14 @@ impl Resource for PtyPgrp { } } - fn fevent(&self) -> Result<()> { + fn fevent(&mut self) -> Result<()> { Err(Error::new(EBADF)) } - fn fevent_count(&self) -> Option { + fn fevent_count(&mut self) -> Option { None } + fn fevent_writable(&mut self) -> bool { + false + } } diff --git a/src/resource.rs b/src/resource.rs index a6dcb4714e..2ad8a7912c 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -11,10 +11,11 @@ pub trait Resource { fn flags(&self) -> usize; fn path(&self, buf: &mut [u8]) -> Result; - fn read(&self, buf: &mut [u8]) -> Result; - fn write(&self, buf: &[u8]) -> Result; + fn read(&self, buf: &mut [u8]) -> Result>; + fn write(&self, buf: &[u8]) -> Result>; fn sync(&self) -> Result; fn fcntl(&mut self, cmd: usize, arg: usize) -> Result; - fn fevent(&self) -> Result<()>; - fn fevent_count(&self) -> Option; + fn fevent(&mut self) -> Result<()>; + fn fevent_count(&mut self) -> Option; + fn fevent_writable(&mut self) -> bool; } diff --git a/src/scheme.rs b/src/scheme.rs index c9c031beb8..f21c73f217 100644 --- a/src/scheme.rs +++ b/src/scheme.rs @@ -6,7 +6,7 @@ use std::str; use syscall::data::Stat; use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT}; use syscall::flag::MODE_CHR; -use syscall::scheme::SchemeMut; +use syscall::scheme::SchemeBlockMut; use master::PtyMaster; use pgrp::PtyPgrp; @@ -30,8 +30,8 @@ impl PtyScheme { } } -impl SchemeMut for PtyScheme { - fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result { +impl SchemeBlockMut for PtyScheme { + fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result> { let path = str::from_utf8(path).or(Err(Error::new(EINVAL)))?.trim_matches('/'); if path.is_empty() { @@ -41,7 +41,7 @@ impl SchemeMut for PtyScheme { let pty = Rc::new(RefCell::new(Pty::new(id))); self.handles.insert(id, Box::new(PtyMaster::new(pty, flags))); - Ok(id) + Ok(Some(id)) } else { let master_id = path.parse::().or(Err(Error::new(EINVAL)))?; let pty = { @@ -54,11 +54,11 @@ impl SchemeMut for PtyScheme { self.handles.insert(id, Box::new(PtySlave::new(pty, flags))); - Ok(id) + Ok(Some(id)) } } - fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result { + fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result> { let handle: Box = { let old_handle = self.handles.get(&old_id).ok_or(Error::new(EBADF))?; @@ -79,35 +79,35 @@ impl SchemeMut for PtyScheme { self.next_id += 1; self.handles.insert(id, handle); - Ok(id) + Ok(Some(id)) } - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { + fn read(&mut self, id: usize, buf: &mut [u8]) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; handle.read(buf) } - fn write(&mut self, id: usize, buf: &[u8]) -> Result { + fn write(&mut self, id: usize, buf: &[u8]) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; handle.write(buf) } - fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result { + fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result> { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; - handle.fcntl(cmd, arg) + handle.fcntl(cmd, arg).map(Some) } - fn fevent(&mut self, id: usize, _flags: usize) -> Result { + fn fevent(&mut self, id: usize, _flags: usize) -> Result> { + let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + handle.fevent().and(Ok(Some(id))) + } + + fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - handle.fevent().and(Ok(id)) + handle.path(buf).map(Some) } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - handle.path(buf) - } - - fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { + fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result> { let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; *stat = Stat { @@ -115,17 +115,17 @@ impl SchemeMut for PtyScheme { ..Default::default() }; - Ok(0) + Ok(Some(0)) } - fn fsync(&mut self, id: usize) -> Result { + fn fsync(&mut self, id: usize) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - handle.sync() + handle.sync().map(Some) } - fn close(&mut self, id: usize) -> Result { + fn close(&mut self, id: usize) -> Result> { drop(self.handles.remove(&id)); - Ok(0) + Ok(Some(0)) } } diff --git a/src/slave.rs b/src/slave.rs index e9aa219dc7..d4ca783147 100644 --- a/src/slave.rs +++ b/src/slave.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::rc::Weak; -use syscall::error::{Error, Result, EINVAL, EPIPE, EWOULDBLOCK}; +use syscall::error::{Error, Result, EINVAL, EPIPE, EAGAIN}; use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; use pty::Pty; @@ -12,6 +12,8 @@ use resource::Resource; pub struct PtySlave { pty: Weak>, flags: usize, + notified_read: bool, + notified_write: bool } impl PtySlave { @@ -19,6 +21,8 @@ impl PtySlave { PtySlave { pty: pty, flags: flags, + notified_read: false, + notified_write: false } } } @@ -44,7 +48,7 @@ impl Resource for PtySlave { } } - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let mut pty = pty_lock.borrow_mut(); @@ -60,28 +64,28 @@ impl Resource for PtySlave { pty.mosi.push_front(packet[i..].to_vec()); } - Ok(i) + Ok(Some(i)) } else if self.flags & O_NONBLOCK == O_NONBLOCK { - Ok(0) + Err(Error::new(EAGAIN)) } else { - Err(Error::new(EWOULDBLOCK)) + Ok(None) } } else { - Ok(0) + Ok(Some(0)) } } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let mut pty = pty_lock.borrow_mut(); if pty.miso.len() >= 64 { - return Err(Error::new(EWOULDBLOCK)); + return Ok(None); } pty.output(buf); - Ok(buf.len()) + Ok(Some(buf.len())) } else { Err(Error::new(EPIPE)) } @@ -110,20 +114,33 @@ impl Resource for PtySlave { } } - fn fevent(&self) -> Result<()> { + fn fevent(&mut self) -> Result<()> { + self.notified_read = false; // resend + self.notified_write = false; Ok(()) } - fn fevent_count(&self) -> Option { + fn fevent_count(&mut self) -> Option { if let Some(pty_lock) = self.pty.upgrade() { let pty = pty_lock.borrow(); if let Some(data) = pty.mosi.front() { - Some(data.len()) + if !self.notified_read { + self.notified_read = true; + Some(data.len()) + } else { + None + } } else { + self.notified_read = false; None } } else { Some(0) } } + fn fevent_writable(&mut self) -> bool { + let notified = self.notified_write; + self.notified_write = true; + !notified + } } diff --git a/src/termios.rs b/src/termios.rs index a9bac08040..13f98c81a9 100644 --- a/src/termios.rs +++ b/src/termios.rs @@ -45,7 +45,7 @@ impl Resource for PtyTermios { } } - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let pty = pty_lock.borrow(); let termios: &[u8] = pty.termios.deref(); @@ -55,13 +55,13 @@ impl Resource for PtyTermios { buf[i] = termios[i]; i += 1; } - Ok(i) + Ok(Some(i)) } else { - Ok(0) + Ok(Some(0)) } } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let mut pty = pty_lock.borrow_mut(); let termios: &mut [u8] = pty.termios.deref_mut(); @@ -71,7 +71,7 @@ impl Resource for PtyTermios { termios[i] = buf[i]; i += 1; } - Ok(i) + Ok(Some(i)) } else { Err(Error::new(EPIPE)) } @@ -92,11 +92,14 @@ impl Resource for PtyTermios { } } - fn fevent(&self) -> Result<()> { + fn fevent(&mut self) -> Result<()> { Err(Error::new(EBADF)) } - fn fevent_count(&self) -> Option { + fn fevent_count(&mut self) -> Option { None } + fn fevent_writable(&mut self) -> bool { + false + } } diff --git a/src/winsize.rs b/src/winsize.rs index a44a07ce50..615861394b 100644 --- a/src/winsize.rs +++ b/src/winsize.rs @@ -45,7 +45,7 @@ impl Resource for PtyWinsize { } } - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let pty = pty_lock.borrow(); let winsize: &[u8] = pty.winsize.deref(); @@ -55,13 +55,13 @@ impl Resource for PtyWinsize { buf[i] = winsize[i]; i += 1; } - Ok(i) + Ok(Some(i)) } else { - Ok(0) + Ok(Some(0)) } } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result> { if let Some(pty_lock) = self.pty.upgrade() { let mut pty = pty_lock.borrow_mut(); let winsize: &mut [u8] = pty.winsize.deref_mut(); @@ -71,7 +71,7 @@ impl Resource for PtyWinsize { winsize[i] = buf[i]; i += 1; } - Ok(i) + Ok(Some(i)) } else { Err(Error::new(EPIPE)) } @@ -92,11 +92,14 @@ impl Resource for PtyWinsize { } } - fn fevent(&self) -> Result<()> { + fn fevent(&mut self) -> Result<()> { Err(Error::new(EBADF)) } - fn fevent_count(&self) -> Option { + fn fevent_count(&mut self) -> Option { None } + fn fevent_writable(&mut self) -> bool { + false + } }