mirror of https://github.com/dswd/vpncloud.git
Added pluggable polling system
This commit is contained in:
parent
1cf1d0687b
commit
d52d7e3aaf
|
@ -4,6 +4,7 @@ This project follows [semantic versioning](http://semver.org).
|
||||||
|
|
||||||
### UNRELEASED
|
### UNRELEASED
|
||||||
|
|
||||||
|
- [added] Added pluggable polling system
|
||||||
- [added] Added documentation
|
- [added] Added documentation
|
||||||
- [changed] Code cleanup
|
- [changed] Code cleanup
|
||||||
- [changed] Updated dependencies
|
- [changed] Updated dependencies
|
||||||
|
|
|
@ -3,11 +3,11 @@ name = "vpncloud"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aligned_alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aligned_alloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"docopt 0.6.81 (registry+https://github.com/rust-lang/crates.io-index)",
|
"docopt 0.6.81 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"epoll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"fnv 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"net2 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"net2 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -32,7 +32,7 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -41,6 +41,11 @@ name = "bitflags"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -56,25 +61,6 @@ dependencies = [
|
||||||
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "epoll"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -96,7 +82,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.12"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -109,7 +95,7 @@ name = "memchr"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -119,7 +105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -131,7 +117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -147,7 +133,7 @@ name = "rand"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -190,7 +176,7 @@ name = "signal"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -205,7 +191,7 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -222,7 +208,7 @@ version = "0.1.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@ time = "0.1"
|
||||||
docopt = "0.6"
|
docopt = "0.6"
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
epoll = "0.3"
|
signal = "0.2"
|
||||||
signal = ">=0.1.4"
|
|
||||||
nix = "0.6"
|
nix = "0.6"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
aligned_alloc = "0.1"
|
aligned_alloc = "0.1"
|
||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
fnv = "1"
|
fnv = "1"
|
||||||
net2 = "0.2"
|
net2 = "0.2"
|
||||||
|
bitflags = "0.7"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3"
|
gcc = "0.3"
|
||||||
|
|
|
@ -7,6 +7,7 @@ use test::Bencher;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::net::{UdpSocket, ToSocketAddrs, Ipv4Addr, SocketAddr, SocketAddrV4};
|
use std::net::{UdpSocket, ToSocketAddrs, Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use super::cloud::GenericCloud;
|
use super::cloud::GenericCloud;
|
||||||
use super::device::{Device, Type};
|
use super::device::{Device, Type};
|
||||||
|
@ -16,8 +17,7 @@ use super::ethernet::{Frame, SwitchTable};
|
||||||
use super::types::{Address, Table, Protocol};
|
use super::types::{Address, Table, Protocol};
|
||||||
use super::ip::Packet;
|
use super::ip::Packet;
|
||||||
use super::util::now as util_now;
|
use super::util::now as util_now;
|
||||||
|
use super::poll::{self, Poll};
|
||||||
use epoll;
|
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn crypto_salsa20(b: &mut Bencher) {
|
fn crypto_salsa20(b: &mut Bencher) {
|
||||||
|
@ -141,13 +141,11 @@ fn now(b: &mut Bencher) {
|
||||||
#[bench]
|
#[bench]
|
||||||
fn epoll_wait(b: &mut Bencher) {
|
fn epoll_wait(b: &mut Bencher) {
|
||||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
let epoll_handle = epoll::create1(0).unwrap();
|
let mut poll_handle = Poll::new(1).unwrap();
|
||||||
let fd = socket.as_raw_fd();
|
let fd = socket.as_raw_fd();
|
||||||
let mut event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLOUT, data: 0};
|
poll_handle.register(fd, poll::WRITE).unwrap();
|
||||||
epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, fd, &mut event).unwrap();
|
|
||||||
let mut events = [epoll::EpollEvent{events: 0, data: 0}; 1];
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
epoll::wait(epoll_handle, &mut events, 1000).unwrap()
|
assert_eq!(poll_handle.wait(1000).unwrap().len(), 1)
|
||||||
});
|
});
|
||||||
b.bytes = 1400;
|
b.bytes = 1400;
|
||||||
}
|
}
|
||||||
|
|
30
src/cloud.rs
30
src/cloud.rs
|
@ -14,7 +14,6 @@ use std::time::Instant;
|
||||||
use std::cmp::{min, max};
|
use std::cmp::{min, max};
|
||||||
|
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
use epoll;
|
|
||||||
use nix::sys::signal::{SIGTERM, SIGQUIT, SIGINT};
|
use nix::sys::signal::{SIGTERM, SIGQUIT, SIGINT};
|
||||||
use signal::trap::Trap;
|
use signal::trap::Trap;
|
||||||
use rand::{random, sample, thread_rng};
|
use rand::{random, sample, thread_rng};
|
||||||
|
@ -25,6 +24,7 @@ use super::device::Device;
|
||||||
use super::udpmessage::{encode, decode, Options, Message};
|
use super::udpmessage::{encode, decode, Options, Message};
|
||||||
use super::crypto::Crypto;
|
use super::crypto::Crypto;
|
||||||
use super::util::{now, Time, Duration, resolve};
|
use super::util::{now, Time, Duration, resolve};
|
||||||
|
use super::poll::{self, Poll};
|
||||||
|
|
||||||
type Hash = BuildHasherDefault<FnvHasher>;
|
type Hash = BuildHasherDefault<FnvHasher>;
|
||||||
|
|
||||||
|
@ -569,34 +569,28 @@ impl<P: Protocol> GenericCloud<P> {
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let dummy_time = Instant::now();
|
let dummy_time = Instant::now();
|
||||||
let trap = Trap::trap(&[SIGINT, SIGTERM, SIGQUIT]);
|
let trap = Trap::trap(&[SIGINT, SIGTERM, SIGQUIT]);
|
||||||
let epoll_handle = try_fail!(epoll::create1(0), "Failed to create epoll handle: {}");
|
let mut poll_handle = try_fail!(Poll::new(3), "Failed to create poll handle: {}");
|
||||||
let socket4_fd = self.socket4.as_raw_fd();
|
let socket4_fd = self.socket4.as_raw_fd();
|
||||||
let socket6_fd = self.socket6.as_raw_fd();
|
let socket6_fd = self.socket6.as_raw_fd();
|
||||||
let device_fd = self.device.as_raw_fd();
|
let device_fd = self.device.as_raw_fd();
|
||||||
let mut socket4_event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLIN, data: 0};
|
try_fail!(poll_handle.register(socket4_fd, poll::READ), "Failed to add ipv4 socket to poll handle: {}");
|
||||||
let mut socket6_event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLIN, data: 1};
|
try_fail!(poll_handle.register(socket6_fd, poll::READ), "Failed to add ipv4 socket to poll handle: {}");
|
||||||
let mut device_event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLIN, data: 2};
|
try_fail!(poll_handle.register(device_fd, poll::READ), "Failed to add ipv4 socket to poll handle: {}");
|
||||||
try_fail!(epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, socket4_fd, &mut socket4_event), "Failed to add ipv4 socket to epoll handle: {}");
|
|
||||||
try_fail!(epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, socket6_fd, &mut socket6_event), "Failed to add ipv6 socket to epoll handle: {}");
|
|
||||||
try_fail!(epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, device_fd, &mut device_event), "Failed to add device to epoll handle: {}");
|
|
||||||
let mut events = [epoll::EpollEvent{events: 0, data: 0}; 3];
|
|
||||||
let mut buffer = [0; 64*1024];
|
let mut buffer = [0; 64*1024];
|
||||||
loop {
|
loop {
|
||||||
let count = try_fail!(epoll::wait(epoll_handle, &mut events, 1000), "Epoll wait failed: {}") as usize;
|
for evt in try_fail!(poll_handle.wait(1000), "Poll wait failed: {}") {
|
||||||
// Process events
|
match evt.fd() {
|
||||||
for evt in events.iter().take(count) {
|
fd if (fd == socket4_fd || fd == socket6_fd) => {
|
||||||
match evt.data {
|
let (size, src) = match evt.fd() {
|
||||||
0 | 1 => {
|
fd if fd == socket4_fd => try_fail!(self.socket4.recv_from(&mut buffer), "Failed to read from ipv4 network socket: {}"),
|
||||||
let (size, src) = match evt.data {
|
fd if fd == socket6_fd => try_fail!(self.socket6.recv_from(&mut buffer), "Failed to read from ipv6 network socket: {}"),
|
||||||
0 => try_fail!(self.socket4.recv_from(&mut buffer), "Failed to read from ipv4 network socket: {}"),
|
|
||||||
1 => try_fail!(self.socket6.recv_from(&mut buffer), "Failed to read from ipv6 network socket: {}"),
|
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
if let Err(e) = decode(&mut buffer[..size], &mut self.crypto).and_then(|(options, msg)| self.handle_net_message(src, options, msg)) {
|
if let Err(e) = decode(&mut buffer[..size], &mut self.crypto).and_then(|(options, msg)| self.handle_net_message(src, options, msg)) {
|
||||||
error!("Error: {}, from: {}", e, src);
|
error!("Error: {}, from: {}", e, src);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
2 => {
|
fd if (fd == device_fd) => {
|
||||||
let start = 64;
|
let start = 64;
|
||||||
let size = try_fail!(self.device.read(&mut buffer[start..]), "Failed to read from tap device: {}");
|
let size = try_fail!(self.device.read(&mut buffer[start..]), "Failed to read from tap device: {}");
|
||||||
if let Err(e) = self.handle_interface_data(&mut buffer, start, start+size) {
|
if let Err(e) = self.handle_interface_data(&mut buffer, start, start+size) {
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
#![cfg_attr(feature = "bench", feature(test))]
|
#![cfg_attr(feature = "bench", feature(test))]
|
||||||
|
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
#[macro_use] extern crate bitflags;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate docopt;
|
extern crate docopt;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate epoll;
|
|
||||||
extern crate signal;
|
extern crate signal;
|
||||||
extern crate nix;
|
extern crate nix;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
@ -26,6 +26,7 @@ pub mod ethernet;
|
||||||
pub mod ip;
|
pub mod ip;
|
||||||
pub mod cloud;
|
pub mod cloud;
|
||||||
pub mod device;
|
pub mod device;
|
||||||
|
pub mod poll;
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
#[cfg(feature = "bench")] mod benches;
|
#[cfg(feature = "bench")] mod benches;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
use libc;
|
||||||
|
|
||||||
|
use std::os::unix::io::RawFd;
|
||||||
|
use std::io;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
bitflags!{
|
||||||
|
pub flags Flags: u32 {
|
||||||
|
const READ = libc::EPOLLIN as u32,
|
||||||
|
const WRITE = libc::EPOLLOUT as u32,
|
||||||
|
const ERROR = libc::EPOLLERR as u32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Event(libc::epoll_event);
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
#[inline]
|
||||||
|
pub fn fd(&self) -> RawFd {
|
||||||
|
self.0.u64 as RawFd
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn flags(&self) -> Flags {
|
||||||
|
Flags::from_bits(self.0.events).expect("Invalid flags set")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn new(fd: RawFd, flags: Flags) -> Self {
|
||||||
|
Event(libc::epoll_event{u64: fd as u64, events: flags.bits})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Event {
|
||||||
|
type Target = libc::epoll_event;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Event {
|
||||||
|
#[inline]
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Poll {
|
||||||
|
fd: RawFd,
|
||||||
|
events: Vec<Event>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Poll {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(max_events: usize) -> io::Result<Self> {
|
||||||
|
let mut events = Vec::with_capacity(max_events);
|
||||||
|
events.resize(max_events, Event::new(0, Flags::empty()));
|
||||||
|
let fd = unsafe { libc::epoll_create(max_events as i32) };
|
||||||
|
if fd == -1 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
Ok(Poll{fd: fd, events: events})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn register(&mut self, fd: RawFd, flags: Flags) -> io::Result<()> {
|
||||||
|
let mut ev = Event::new(fd, flags);
|
||||||
|
let res = unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_ADD, fd, &mut ev as &mut libc::epoll_event) };
|
||||||
|
if res == -1 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn unregister(&mut self, fd: RawFd) -> io::Result<()> {
|
||||||
|
let mut ev = Event::new(fd, Flags::empty());
|
||||||
|
let res = unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_DEL, fd, &mut ev as &mut libc::epoll_event) };
|
||||||
|
if res == -1 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn wait(&mut self, timeout_millis: u32) -> io::Result<&[Event]> {
|
||||||
|
let res = unsafe { libc::epoll_wait(self.fd, &mut self.events[0] as &mut libc::epoll_event, self.events.len() as i32, timeout_millis as i32) };
|
||||||
|
if res == -1 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
Ok(&self.events[0..res as usize])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Poll {
|
||||||
|
#[inline]
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { libc::close(self.fd) };
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
mod epoll;
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
pub use self::epoll::*;
|
Loading…
Reference in New Issue