alnyan/yggdrasil: Add LookupHost and TimerFd
This commit is contained in:
@@ -7175,6 +7175,7 @@ name = "yggdrasil-abi"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
|
"rustc-std-workspace-alloc",
|
||||||
"rustc-std-workspace-core",
|
"rustc-std-workspace-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub mod pipe;
|
|||||||
pub mod poll;
|
pub mod poll;
|
||||||
pub mod shared_memory;
|
pub mod shared_memory;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
|
pub mod timer;
|
||||||
|
|
||||||
// Public exports
|
// Public exports
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#![unstable(feature = "yggdrasil_os", issue = "none")]
|
||||||
|
|
||||||
|
use crate::io;
|
||||||
|
use crate::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||||
|
use crate::sys::cvt_io;
|
||||||
|
use crate::sys::fd::FileDesc;
|
||||||
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
use yggdrasil_rt::sys as syscall;
|
||||||
|
|
||||||
|
#[unstable(feature = "yggdrasil_os", issue = "none")]
|
||||||
|
pub struct TimerFd(FileDesc);
|
||||||
|
|
||||||
|
impl TimerFd {
|
||||||
|
#[unstable(feature = "yggdrasil_os", issue = "none")]
|
||||||
|
pub fn new(repeat: bool) -> io::Result<Self> {
|
||||||
|
let raw = cvt_io(unsafe { syscall::create_timer(repeat) })?;
|
||||||
|
let fd = unsafe { FileDesc::from_raw_fd(raw) };
|
||||||
|
Ok(Self(fd))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(&mut self, timeout: Duration) -> io::Result<()> {
|
||||||
|
let tval = timeout.as_micros();
|
||||||
|
cvt_io(unsafe { syscall::write(self.0.as_raw_fd(), &tval.to_ne_bytes()) })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "yggdrasil_os", issue = "none")]
|
||||||
|
impl AsRawFd for TimerFd {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
use yggdrasil_rt::net::dns::{
|
||||||
|
self, DnsClass, DnsMessage, DnsRecordData, DnsReplyCode, DnsType, UdpRequester,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::io;
|
||||||
|
use crate::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
|
||||||
|
use crate::os::{
|
||||||
|
fd::AsRawFd,
|
||||||
|
yggdrasil::io::{poll::PollChannel, timer::TimerFd},
|
||||||
|
};
|
||||||
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
pub struct LookupHost {
|
||||||
|
addresses: Vec<IpAddr>,
|
||||||
|
port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DnsRequester {
|
||||||
|
nameserver: SocketAddr,
|
||||||
|
|
||||||
|
poll: PollChannel,
|
||||||
|
|
||||||
|
timer: TimerFd,
|
||||||
|
socket: UdpSocket,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO remove hardcoded nameserver
|
||||||
|
// Maybe use local resolver?
|
||||||
|
const NAMESERVER: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(11, 0, 0, 1)), 53);
|
||||||
|
|
||||||
|
impl DnsRequester {
|
||||||
|
pub fn new(nameserver: SocketAddr) -> io::Result<Self> {
|
||||||
|
let mut poll = PollChannel::new()?;
|
||||||
|
let timer = TimerFd::new(false)?;
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
||||||
|
|
||||||
|
poll.add(timer.as_raw_fd())?;
|
||||||
|
poll.add(socket.as_raw_fd())?;
|
||||||
|
|
||||||
|
Ok(Self { nameserver, poll, timer, socket })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UdpRequester for DnsRequester {
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn send_message(&mut self, message: &[u8]) -> io::Result<()> {
|
||||||
|
self.socket.send_to(message, &self.nameserver)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_message<F: Fn(&[u8]) -> Option<DnsMessage>>(
|
||||||
|
&mut self,
|
||||||
|
map: F,
|
||||||
|
) -> io::Result<DnsMessage> {
|
||||||
|
let mut buffer = [0; 2048];
|
||||||
|
|
||||||
|
self.timer.start(Duration::from_millis(500));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (poll_fd, result) = self.poll.wait(None)?.unwrap();
|
||||||
|
result?;
|
||||||
|
|
||||||
|
match poll_fd {
|
||||||
|
fd if fd == self.socket.as_raw_fd() => {
|
||||||
|
let (len, _) = self.socket.recv_from(&mut buffer)?;
|
||||||
|
|
||||||
|
if let Some(message) = map(&buffer[..len]) {
|
||||||
|
return Ok(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fd if fd == self.timer.as_raw_fd() => {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::TimedOut, "DNS query timed out"));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LookupHost {
|
||||||
|
pub fn port(&self) -> u16 {
|
||||||
|
self.port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for LookupHost {
|
||||||
|
type Item = SocketAddr;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<SocketAddr> {
|
||||||
|
let ip = self.addresses.pop()?;
|
||||||
|
Some(SocketAddr::new(ip, self.port))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for LookupHost {
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn try_from(s: &str) -> io::Result<Self> {
|
||||||
|
use crate::str::FromStr;
|
||||||
|
|
||||||
|
let (hostname, port) = s
|
||||||
|
.rsplit_once(':')
|
||||||
|
.ok_or(io::Error::new(io::ErrorKind::InvalidData, "Invalid host:port combination"))?;
|
||||||
|
let port =
|
||||||
|
u16::from_str(port).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
Self::try_from((hostname, port))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn try_from((hostname, port): (&'a str, u16)) -> io::Result<Self> {
|
||||||
|
// TODO randomize xid/cookie
|
||||||
|
let mut requester = DnsRequester::new(NAMESERVER)?;
|
||||||
|
let message = dns::perform_query(&mut requester, hostname, DnsType::A, 12341, 0x12313121)?;
|
||||||
|
|
||||||
|
if message.reply_code != DnsReplyCode::NO_ERROR {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "DNS server returned error"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut addresses = vec![];
|
||||||
|
|
||||||
|
for answer in message.answers {
|
||||||
|
let Some(name) = answer.name.0.as_ref() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let name = name.trim_end_matches('.');
|
||||||
|
if name != hostname {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match (answer.ty, answer.class, &answer.rdata) {
|
||||||
|
(DnsType::A, DnsClass::IN, DnsRecordData::A(address)) => {
|
||||||
|
addresses.push(IpAddr::V4(u32::from(*address).into()));
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self { addresses, port })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,58 +1,15 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
mod dns;
|
||||||
// use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
|
||||||
// use crate::os::yggdrasil::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
|
||||||
// use crate::sys::io::FileDesc;
|
|
||||||
// use crate::sys_common::{AsInner, FromInner, IntoInner};
|
|
||||||
// use crate::time::Duration;
|
|
||||||
//
|
|
||||||
// pub use crate::sys::{cvt, cvt_r};
|
|
||||||
|
|
||||||
// pub use super::yggdrasil_rt::netc;
|
|
||||||
|
|
||||||
mod tcp_listener;
|
mod tcp_listener;
|
||||||
mod tcp_stream;
|
mod tcp_stream;
|
||||||
mod udp;
|
mod udp;
|
||||||
|
|
||||||
|
pub use dns::LookupHost;
|
||||||
pub use tcp_listener::TcpListener;
|
pub use tcp_listener::TcpListener;
|
||||||
pub use tcp_stream::TcpStream;
|
pub use tcp_stream::TcpStream;
|
||||||
pub use udp::UdpSocket;
|
pub use udp::UdpSocket;
|
||||||
|
|
||||||
use crate::net::SocketAddr;
|
|
||||||
|
|
||||||
pub struct LookupHost(!);
|
|
||||||
|
|
||||||
impl LookupHost {
|
|
||||||
pub fn port(&self) -> u16 {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for LookupHost {
|
|
||||||
type Item = SocketAddr;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<SocketAddr> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&str> for LookupHost {
|
|
||||||
type Error = crate::io::Error;
|
|
||||||
|
|
||||||
fn try_from(_s: &str) -> crate::io::Result<Self> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
|
|
||||||
type Error = crate::io::Error;
|
|
||||||
|
|
||||||
fn try_from(_s: (&'a str, u16)) -> crate::io::Result<Self> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub type wrlen_t = usize;
|
// pub type wrlen_t = usize;
|
||||||
|
|
||||||
// #[derive(Debug)]
|
// #[derive(Debug)]
|
||||||
|
|||||||
Reference in New Issue
Block a user