use std::os::unix::io::RawFd;
use std::cell::RefCell;
use std::boxed::Box;
use nix::unistd;
use slab::Slab;
use error::Error;
use handler::*;
use protocol::{IOProtocol, Action};
use poll::*;
pub struct SyncHandler<F: IOProtocol> {
id: usize,
epfd: EpollFd,
handlers: Slab<RefCell<Box<Handler<EpollEvent>>>, usize>,
eproto: F,
rproto: F::Protocol,
}
impl<F: IOProtocol> SyncHandler<F> {
pub fn new(epfd: EpollFd,
id: usize,
eproto: F,
rproto: F::Protocol,
max_handlers: usize)
-> SyncHandler<F> {
trace!("new()");
SyncHandler {
id: id,
epfd: epfd,
handlers: Slab::with_capacity(max_handlers),
eproto: eproto,
rproto: rproto,
}
}
fn notify(&mut self, fd: RawFd, id: usize, event: &EpollEvent) {
trace!("notify(): {:?}; fd {:?}", &id, &fd);
let events = event.events;
if events.contains(EPOLLRDHUP) || events.contains(EPOLLHUP) {
trace!("socket's fd {}: EPOLLHUP", fd);
match self.handlers.remove(id) {
None => error!("on_close(): handler not found"),
Some(_) => {}
}
perror!("unregister()", self.epfd.unregister(fd));
perror!("close()", unistd::close(fd));
} else {
let handler = &mut self.handlers[id];
handler.borrow_mut().ready(event);
}
}
}
impl<F: IOProtocol> Handler<EpollEvent> for SyncHandler<F> {
fn is_terminated(&self) -> bool {
false
}
fn ready(&mut self, ev: &EpollEvent) {
trace!("ready()");
match self.eproto.decode(ev.data) {
Action::New(proto, fd) => {
let next = if proto.into() == 0_usize {
self.rproto
} else {
proto
};
let epfd = self.epfd;
let proto = self.eproto;
if let Ok(id) = self.handlers
.insert(RefCell::new(proto.get_handler(next, epfd, self.id))) {
trace!("ready(): new handler ({} {})", next.into(), &id);
let action: Action<F> = Action::Notify(id, fd);
let interest = EpollEvent {
events: EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP | EPOLLET,
data: self.eproto.encode(action),
};
match self.epfd.reregister(fd, &interest) {
Ok(_) => self.notify(fd, id, ev),
Err(e) => report_err!("reregister()", e),
}
} else {
}
}
Action::Notify(id, fd) => self.notify(fd, id, ev),
}
}
}