vpncloud/src/poll/epoll.rs

91 lines
2.8 KiB
Rust
Raw Normal View History

2017-07-22 14:49:53 +00:00
// VpnCloud - Peer-to-Peer VPN
2019-02-19 21:04:21 +00:00
// Copyright (C) 2015-2019 Dennis Schwerdel
2017-07-22 14:49:53 +00:00
// This software is licensed under GPL-3 or newer (see LICENSE.md)
2016-06-30 08:05:37 +00:00
use libc;
2019-03-01 22:12:19 +00:00
use crate::device::Device;
2019-12-04 08:32:35 +00:00
use std::{io, os::unix::io::RawFd};
2019-02-21 21:41:36 +00:00
use super::WaitResult;
2019-12-04 08:32:35 +00:00
use crate::{device::Type, net::Socket};
2019-02-21 21:41:36 +00:00
pub struct EpollWait {
poll_fd: RawFd,
event: libc::epoll_event,
socketv4: RawFd,
socketv6: RawFd,
device: RawFd,
2019-12-04 08:32:35 +00:00
timeout: u32
2016-06-30 08:05:37 +00:00
}
2019-02-21 21:41:36 +00:00
impl EpollWait {
2019-12-04 08:32:35 +00:00
pub fn new<S: Socket>(socketv4: &S, socketv6: &S, device: &dyn Device, timeout: u32) -> io::Result<Self> {
2019-03-02 11:23:12 +00:00
Self::create(socketv4, socketv6, device, timeout, libc::EPOLLIN as u32)
}
2019-12-04 08:32:35 +00:00
pub fn testing<S: Socket>(socketv4: &S, socketv6: &S, device: &dyn Device, timeout: u32) -> io::Result<Self> {
Self::create(socketv4, socketv6, device, timeout, (libc::EPOLLIN | libc::EPOLLOUT) as u32)
2019-03-02 11:23:12 +00:00
}
2019-12-04 08:32:35 +00:00
fn create<S: Socket>(
socketv4: &S, socketv6: &S, device: &dyn Device, timeout: u32, flags: u32
) -> io::Result<Self> {
let mut event = libc::epoll_event { u64: 0, events: 0 };
let poll_fd = unsafe { libc::epoll_create(3) };
2019-02-21 21:41:36 +00:00
if poll_fd == -1 {
2019-12-04 08:32:35 +00:00
return Err(io::Error::last_os_error())
2016-06-30 08:05:37 +00:00
}
2019-02-21 21:41:36 +00:00
let raw_fds = if device.get_type() != Type::Dummy {
vec![socketv4.as_raw_fd(), socketv6.as_raw_fd(), device.as_raw_fd()]
} else {
vec![socketv4.as_raw_fd(), socketv6.as_raw_fd()]
};
for fd in raw_fds {
event.u64 = fd as u64;
2019-03-02 11:23:12 +00:00
event.events = flags;
2019-02-21 21:41:36 +00:00
let res = unsafe { libc::epoll_ctl(poll_fd, libc::EPOLL_CTL_ADD, fd, &mut event) };
if res == -1 {
2019-12-04 08:32:35 +00:00
return Err(io::Error::last_os_error())
2019-02-21 21:41:36 +00:00
}
2016-06-30 08:05:37 +00:00
}
2019-02-21 21:41:36 +00:00
Ok(Self {
poll_fd,
event,
socketv4: socketv4.as_raw_fd(),
socketv6: socketv6.as_raw_fd(),
device: device.as_raw_fd(),
timeout
})
2016-06-30 08:05:37 +00:00
}
2019-02-21 21:41:36 +00:00
}
2016-06-30 08:05:37 +00:00
2019-02-21 21:41:36 +00:00
impl Drop for EpollWait {
fn drop(&mut self) {
unsafe { libc::close(self.poll_fd) };
2016-06-30 08:05:37 +00:00
}
}
2019-02-21 21:41:36 +00:00
impl Iterator for EpollWait {
type Item = WaitResult;
fn next(&mut self) -> Option<Self::Item> {
Some(match unsafe { libc::epoll_wait(self.poll_fd, &mut self.event, 1, self.timeout as i32) } {
-1 => WaitResult::Error(io::Error::last_os_error()),
0 => WaitResult::Timeout,
2019-12-04 08:32:35 +00:00
1 => {
if self.event.u64 == self.socketv4 as u64 {
WaitResult::SocketV4
} else if self.event.u64 == self.socketv6 as u64 {
WaitResult::SocketV6
} else if self.event.u64 == self.device as u64 {
WaitResult::Device
} else {
unreachable!()
}
}
2019-02-21 21:41:36 +00:00
_ => unreachable!()
})
2016-06-30 08:05:37 +00:00
}
}