Support events
This commit is contained in:
+13
@@ -50,8 +50,21 @@ fn main() -> Result<(), Box<::std::error::Error>> {
|
||||
|
||||
true
|
||||
});
|
||||
|
||||
if let Some(err) = error {
|
||||
return Err(Box::new(err));
|
||||
}
|
||||
|
||||
scheme.post_fevents(&mut scheme_file)?;
|
||||
}
|
||||
}
|
||||
fn post_fevent(file: &mut File, id: usize, flag: usize) -> io::Result<()> {
|
||||
file.write(&syscall::Packet {
|
||||
a: syscall::SYS_FEVENT,
|
||||
b: id,
|
||||
c: flag,
|
||||
d: 1,
|
||||
..Default::default()
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
+51
-24
@@ -1,27 +1,28 @@
|
||||
use std::collections::BTreeMap;
|
||||
use post_fevent;
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
fs::File,
|
||||
io
|
||||
};
|
||||
use syscall::{flag::*, error::*, Error, SchemeBlockMut, Result};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Handle {
|
||||
flags: usize,
|
||||
fevent: usize,
|
||||
notified_read: bool,
|
||||
notified_write: bool,
|
||||
|
||||
path: Option<String>,
|
||||
remote: Option<usize>,
|
||||
buffer: Vec<u8>
|
||||
}
|
||||
impl Handle {
|
||||
pub fn accept(&mut self) -> Self {
|
||||
Self {
|
||||
flags: 0,
|
||||
path: None,
|
||||
remote: self.remote.take(),
|
||||
buffer: Vec::new()
|
||||
}
|
||||
}
|
||||
pub fn copy(&self) -> Self {
|
||||
Self {
|
||||
flags: self.flags,
|
||||
path: None,
|
||||
remote: self.remote,
|
||||
buffer: Vec::new()
|
||||
remote: self.remote.take(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +33,25 @@ pub struct ChanScheme {
|
||||
listeners: BTreeMap<String, usize>,
|
||||
next_id: usize
|
||||
}
|
||||
impl ChanScheme {
|
||||
pub fn post_fevents(&mut self, file: &mut File) -> io::Result<()> {
|
||||
for (id, handle) in &mut self.handles {
|
||||
if !handle.notified_write {
|
||||
handle.notified_write = true;
|
||||
post_fevent(file, *id, EVENT_WRITE)?;
|
||||
}
|
||||
if !handle.buffer.is_empty() {
|
||||
if !handle.notified_read {
|
||||
handle.notified_read = true;
|
||||
post_fevent(file, *id, EVENT_READ)?;
|
||||
}
|
||||
} else {
|
||||
handle.notified_read = false;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl SchemeBlockMut for ChanScheme {
|
||||
fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
|
||||
let path = ::std::str::from_utf8(path).unwrap_or("");
|
||||
@@ -44,12 +64,8 @@ impl SchemeBlockMut for ChanScheme {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
|
||||
let mut handle = Handle {
|
||||
flags: 0,
|
||||
path: None,
|
||||
remote: None,
|
||||
buffer: Vec::new()
|
||||
};
|
||||
let mut handle = Handle::default();
|
||||
handle.flags = flags;
|
||||
|
||||
let id = self.next_id;
|
||||
if flags & O_CREAT == O_CREAT {
|
||||
@@ -67,11 +83,11 @@ impl SchemeBlockMut for ChanScheme {
|
||||
fn dup(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
|
||||
match buf {
|
||||
b"listen" => {
|
||||
let mut handle = match self.handles.get(&id) {
|
||||
Some(ref handle) if handle.path.is_some() => handle.copy(),
|
||||
let (flags, remote) = match self.handles.get(&id) {
|
||||
Some(ref handle) if handle.path.is_some() => (handle.flags, handle.remote),
|
||||
_ => return Err(Error::new(EBADF))
|
||||
};
|
||||
if let Some(remote) = handle.remote {
|
||||
if let Some(remote) = remote {
|
||||
let new_id = self.next_id;
|
||||
let mut clone = self.handles.get_mut(&id).map(Handle::accept).unwrap();
|
||||
|
||||
@@ -81,7 +97,7 @@ impl SchemeBlockMut for ChanScheme {
|
||||
let mut remote = self.handles.get_mut(&remote).unwrap();
|
||||
remote.remote = Some(new_id);
|
||||
Ok(Some(new_id))
|
||||
} else if handle.flags & O_NONBLOCK == O_NONBLOCK {
|
||||
} else if flags & O_NONBLOCK == O_NONBLOCK {
|
||||
Err(Error::new(EAGAIN))
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -95,8 +111,8 @@ impl SchemeBlockMut for ChanScheme {
|
||||
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result<Option<usize>> {
|
||||
match self.handles.get_mut(&id) {
|
||||
Some(handle) => match cmd {
|
||||
::syscall::F_GETFL => Ok(Some(handle.flags)),
|
||||
::syscall::F_SETFL => {
|
||||
F_GETFL => Ok(Some(handle.flags)),
|
||||
F_SETFL => {
|
||||
handle.flags = arg;
|
||||
Ok(Some(0))
|
||||
},
|
||||
@@ -105,6 +121,17 @@ impl SchemeBlockMut for ChanScheme {
|
||||
_ => Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
fn fevent(&mut self, id: usize, flags: usize) -> Result<Option<usize>> {
|
||||
match self.handles.get_mut(&id) {
|
||||
Some(handle) => {
|
||||
handle.fevent = flags;
|
||||
handle.notified_read = false;
|
||||
handle.notified_write = false;
|
||||
Ok(Some(id))
|
||||
},
|
||||
_ => Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
|
||||
let remote = match self.handles.get(&id) {
|
||||
Some(handle) if handle.path.is_none() => handle.remote,
|
||||
|
||||
Reference in New Issue
Block a user