net: implement new connect options
This commit is contained in:
parent
e43b7ee44b
commit
98fe60bc12
@ -548,8 +548,15 @@ impl PacketSocket for RawSocket {
|
||||
}
|
||||
|
||||
impl TcpSocket {
|
||||
pub fn connect(remote: SocketAddr) -> Result<(SocketAddr, Arc<TcpSocket>), Error> {
|
||||
block!(Self::connect_async(remote).await)?
|
||||
pub fn connect(
|
||||
remote: SocketAddr,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<(SocketAddr, Arc<TcpSocket>), Error> {
|
||||
let future = Self::connect_async(remote);
|
||||
match timeout {
|
||||
Some(timeout) => block!(run_with_timeout(timeout, future).await)?.into(),
|
||||
None => block!(future.await)?,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accept_remote(
|
||||
|
@ -7,6 +7,7 @@ use core::{
|
||||
use alloc::vec::Vec;
|
||||
use futures_util::{future::BoxFuture, Future, FutureExt};
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
// 1..32ms, tick every 1ms
|
||||
static SHORT_TERM_SLEEPS: IrqSafeSpinlock<TimerWheel<32>> =
|
||||
@ -143,6 +144,15 @@ pub fn run_with_timeout<'a, T: 'a, F: Future<Output = T> + Send + 'a>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<FutureTimeout<Result<T, Error>>> for Result<T, Error> {
|
||||
fn from(value: FutureTimeout<Result<T, Error>>) -> Self {
|
||||
match value {
|
||||
FutureTimeout::Ok(res) => res,
|
||||
FutureTimeout::Timeout => Err(Error::TimedOut),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the runtime's time
|
||||
pub fn tick(_now: Duration) {
|
||||
SHORT_TERM_SLEEPS.lock().tick();
|
||||
|
@ -3,7 +3,7 @@ use core::{mem::MaybeUninit, net::SocketAddr};
|
||||
use abi::{
|
||||
error::Error,
|
||||
io::RawFd,
|
||||
net::{SocketOption, SocketType},
|
||||
net::{SocketConnect, SocketOption, SocketType},
|
||||
};
|
||||
use libk::{task::thread::Thread, vfs::File};
|
||||
use ygg_driver_net_core::socket::{RawSocket, TcpListener, TcpSocket, UdpSocket};
|
||||
@ -12,26 +12,26 @@ use crate::syscall::run_with_io;
|
||||
|
||||
// Network
|
||||
pub(crate) fn connect_socket(
|
||||
socket_fd: Option<RawFd>,
|
||||
remote: &SocketAddr,
|
||||
ty: SocketType,
|
||||
connect: &mut SocketConnect,
|
||||
local_result: &mut MaybeUninit<SocketAddr>,
|
||||
) -> Result<RawFd, Error> {
|
||||
assert!(socket_fd.is_none());
|
||||
|
||||
let thread = Thread::current();
|
||||
let process = thread.process();
|
||||
|
||||
run_with_io(&process, |mut io| {
|
||||
let (local, file) = match ty {
|
||||
SocketType::TcpStream => {
|
||||
let (local, socket) = TcpSocket::connect((*remote).into())?;
|
||||
(local, File::from_stream_socket(socket))
|
||||
let (local, fd) = match connect {
|
||||
&mut SocketConnect::Udp(fd, remote) => {
|
||||
todo!("UDP socket connect");
|
||||
}
|
||||
&mut SocketConnect::Tcp(remote, timeout) => {
|
||||
let (local, socket) = TcpSocket::connect(remote.into(), timeout)?;
|
||||
let fd = io
|
||||
.files
|
||||
.place_file(File::from_stream_socket(socket), true)?;
|
||||
(local.into(), fd)
|
||||
}
|
||||
_ => return Err(Error::InvalidArgument),
|
||||
};
|
||||
let fd = io.files.place_file(file, true)?;
|
||||
local_result.write(local.into());
|
||||
local_result.write(local);
|
||||
Ok(fd)
|
||||
})
|
||||
}
|
||||
|
@ -27,4 +27,5 @@ enum Error(u32) {
|
||||
HostUnreachable = 24,
|
||||
UndefinedSyscall = 25,
|
||||
DirectoryNotEmpty = 26,
|
||||
NotConnected = 27,
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
extern {
|
||||
type Duration = core::time::Duration;
|
||||
type SocketAddr = core::net::SocketAddr;
|
||||
type AtomicU32 = core::sync::atomic::AtomicU32;
|
||||
|
||||
// TODO "tagged union" enums are not yet implemented
|
||||
@ -15,7 +14,9 @@ extern {
|
||||
#[thin]
|
||||
type ExitCode = yggdrasil_abi::process::ExitCode;
|
||||
|
||||
type SocketAddr = core::net::SocketAddr;
|
||||
type SocketOption = yggdrasil_abi::net::SocketOption;
|
||||
type SocketConnect = yggdrasil_abi::net::SocketConnect;
|
||||
|
||||
type SentMessage = yggdrasil_abi::io::SentMessage;
|
||||
type ReceivedMessageMetadata = yggdrasil_abi::io::ReceivedMessageMetadata;
|
||||
@ -122,7 +123,7 @@ syscall receive_message(
|
||||
) -> Result<()>;
|
||||
|
||||
// Network
|
||||
syscall connect_socket(sock_fd: Option<RawFd>, remote: &SocketAddr, ty: SocketType, local: &mut MaybeUninit<SocketAddr>) -> Result<RawFd>;
|
||||
syscall connect_socket(connect: &mut SocketConnect, local: &mut MaybeUninit<SocketAddr>) -> Result<RawFd>;
|
||||
syscall bind_socket(address: &SocketAddr, ty: SocketType) -> Result<RawFd>;
|
||||
syscall accept(sock_fd: RawFd, remote: &mut MaybeUninit<SocketAddr>) -> Result<RawFd>;
|
||||
|
||||
|
@ -11,6 +11,7 @@ pub mod types;
|
||||
use core::time::Duration;
|
||||
|
||||
pub use crate::generated::SocketType;
|
||||
use crate::io::RawFd;
|
||||
|
||||
pub use types::{
|
||||
ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
@ -19,11 +20,15 @@ pub use types::{
|
||||
MacAddress,
|
||||
};
|
||||
|
||||
// primitive_enum! {
|
||||
// #[doc = "Defines a type of a socket"]
|
||||
// pub enum SocketType: u32 {
|
||||
// }
|
||||
// }
|
||||
/// Describes a socket connect operation
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SocketConnect {
|
||||
/// Connect a TCP socket with optional timeout.
|
||||
Tcp(core::net::SocketAddr, Option<Duration>),
|
||||
/// "Connect" an UDP socket, this just sets the sender's address in the socket so
|
||||
/// the caller can then use send().
|
||||
Udp(RawFd, core::net::SocketAddr),
|
||||
}
|
||||
|
||||
/// Describes a method to query an interface
|
||||
#[derive(Clone, Debug)]
|
||||
@ -47,6 +52,8 @@ pub enum SocketOption<'a> {
|
||||
UnbindInterface,
|
||||
/// (Read-only) Hardware address of the bound interface
|
||||
BoundHardwareAddress(MacAddress),
|
||||
/// (Read-only) Remote socket address
|
||||
PeerAddress(Option<core::net::SocketAddr>),
|
||||
/// If set, reception will return [crate::error::Error::WouldBlock] if the socket has
|
||||
/// no data in its queue/buffer.
|
||||
NonBlocking(bool),
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! Yggdrasil OS application runtime
|
||||
#![feature(rustc_private)]
|
||||
#![feature(rustc_private, decl_macro)]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
#![allow(nonstandard_style)]
|
||||
|
@ -1,6 +1,31 @@
|
||||
//! Network-related functions and types
|
||||
|
||||
pub use abi::net::{MacAddress, SocketInterfaceQuery, SocketOption, SocketType};
|
||||
use core::{mem::MaybeUninit, net::SocketAddr, time::Duration};
|
||||
|
||||
pub use abi::net::{MacAddress, SocketConnect, SocketInterfaceQuery, SocketOption, SocketType};
|
||||
use abi::{error::Error, io::RawFd};
|
||||
|
||||
use crate::sys;
|
||||
|
||||
macro socket_option_variant {
|
||||
($opt:ident: bool) => { $crate::net::SocketOption::$opt(false) },
|
||||
($opt:ident: Option) => { $crate::net::SocketOption::$opt(None) },
|
||||
($opt:ident: int) => { $crate::net::SocketOption::$opt(0) }
|
||||
}
|
||||
|
||||
/// Helper macro for getting a [SocketOption] with 1 argument
|
||||
pub macro get_socket_option1($fd:expr, $opt:ident: $ty:tt) {{
|
||||
let mut option = socket_option_variant!($opt: $ty);
|
||||
match unsafe { $crate::sys::get_socket_option($fd, &mut option) } {
|
||||
Ok(()) => {
|
||||
let $crate::net::SocketOption::$opt(value) = option else { unreachable!() };
|
||||
Ok(value)
|
||||
}
|
||||
Err(error) => {
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
#[cfg(any(feature = "alloc", rust_analyzer))]
|
||||
pub mod dns {
|
||||
@ -52,3 +77,24 @@ pub mod dns {
|
||||
Ok(message)
|
||||
}
|
||||
}
|
||||
|
||||
fn connect_inner(connect: &mut SocketConnect) -> Result<(SocketAddr, RawFd), Error> {
|
||||
let mut local = MaybeUninit::uninit();
|
||||
let fd = unsafe { sys::connect_socket(connect, &mut local) }?;
|
||||
let local = unsafe { local.assume_init() };
|
||||
Ok((local, fd))
|
||||
}
|
||||
|
||||
/// Connect to a TCP listener
|
||||
pub fn connect_tcp(
|
||||
remote: SocketAddr,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<(SocketAddr, RawFd), Error> {
|
||||
connect_inner(&mut SocketConnect::Tcp(remote.into(), timeout))
|
||||
}
|
||||
|
||||
/// "Connect" an UDP socket
|
||||
pub fn connect_udp(socket_fd: RawFd, remote: SocketAddr) -> Result<(), Error> {
|
||||
connect_inner(&mut SocketConnect::Udp(socket_fd, remote.into()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user