2017-07-22 14:49:53 +00:00
|
|
|
// VpnCloud - Peer-to-Peer VPN
|
2020-05-28 07:03:48 +00:00
|
|
|
// Copyright (C) 2015-2020 Dennis Schwerdel
|
2017-07-22 14:49:53 +00:00
|
|
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
|
|
|
|
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,
|
2020-02-20 15:25:35 +00:00
|
|
|
socket: RawFd,
|
2019-02-21 21:41:36 +00:00
|
|
|
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 {
|
2020-02-20 15:25:35 +00:00
|
|
|
pub fn new<S: Socket>(socket: &S, device: &dyn Device, timeout: u32) -> io::Result<Self> {
|
|
|
|
Self::create(socket, device, timeout, libc::EPOLLIN as u32)
|
2019-03-02 11:23:12 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 15:25:35 +00:00
|
|
|
pub fn testing<S: Socket>(socket: &S, device: &dyn Device, timeout: u32) -> io::Result<Self> {
|
|
|
|
Self::create(socket, device, timeout, (libc::EPOLLIN | libc::EPOLLOUT) as u32)
|
2019-03-02 11:23:12 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 15:25:35 +00:00
|
|
|
fn create<S: Socket>(socket: &S, device: &dyn Device, timeout: u32, flags: u32) -> io::Result<Self> {
|
2019-12-04 08:32:35 +00:00
|
|
|
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 {
|
2020-02-20 15:25:35 +00:00
|
|
|
vec![socket.as_raw_fd(), device.as_raw_fd()]
|
2019-02-21 21:41:36 +00:00
|
|
|
} else {
|
2020-02-20 15:25:35 +00:00
|
|
|
vec![socket.as_raw_fd()]
|
2019-02-21 21:41:36 +00:00
|
|
|
};
|
|
|
|
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
|
|
|
}
|
2020-05-28 07:03:48 +00:00
|
|
|
Ok(Self { poll_fd, event, socket: socket.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 => {
|
2020-02-20 15:25:35 +00:00
|
|
|
if self.event.u64 == self.socket as u64 {
|
|
|
|
WaitResult::Socket
|
2019-12-04 08:32:35 +00:00
|
|
|
} 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
|
|
|
}
|
|
|
|
}
|