mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 16:26:48 +00:00
uevent should be format Enum of smoltcp socket should be optimized. need to add interface for routing subsys actix is still not abled to run. clean some casual added code to other places
149 lines
4.7 KiB
Rust
149 lines
4.7 KiB
Rust
use crate::net::{Iface, NET_DEVICES};
|
||
use alloc::sync::Arc;
|
||
use system_error::SystemError::{self, *};
|
||
|
||
pub mod port;
|
||
pub use port::PortManager;
|
||
|
||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||
pub enum Types {
|
||
Raw,
|
||
Icmp,
|
||
Udp,
|
||
Tcp,
|
||
Dhcpv4,
|
||
Dns,
|
||
}
|
||
|
||
/**
|
||
* 目前,以下设计仍然没有考虑多网卡的listen问题,仅只解决了socket在绑定单网卡下的问题。
|
||
*/
|
||
|
||
#[derive(Debug)]
|
||
pub struct BoundInner {
|
||
handle: smoltcp::iface::SocketHandle,
|
||
iface: Arc<dyn Iface>,
|
||
// inner: Vec<(smoltcp::iface::SocketHandle, Arc<dyn Iface>)>
|
||
// address: smoltcp::wire::IpAddress,
|
||
}
|
||
|
||
impl BoundInner {
|
||
/// # `bind`
|
||
/// 将socket绑定到指定的地址上,置入指定的网络接口中
|
||
pub fn bind<T>(
|
||
socket: T,
|
||
// socket_type: Types,
|
||
address: &smoltcp::wire::IpAddress,
|
||
) -> Result<Self, SystemError>
|
||
where
|
||
T: smoltcp::socket::AnySocket<'static>,
|
||
{
|
||
if address.is_unspecified() {
|
||
// let inner = Vec::new();
|
||
// for (_, iface) in *NET_DEVICES.read_irqsave() {
|
||
// let handle = iface.sockets().lock_no_preempt().add(socket);
|
||
// iface
|
||
// }
|
||
// 强绑VirtualIO
|
||
log::debug!("Not bind to any iface, bind to virtIO");
|
||
let iface = NET_DEVICES
|
||
.read_irqsave()
|
||
.get(&0)
|
||
.expect("??bind without virtIO, serious?")
|
||
.clone();
|
||
let handle = iface.sockets().lock_no_preempt().add(socket);
|
||
return Ok(Self { handle, iface });
|
||
} else {
|
||
let iface = get_iface_to_bind(address).ok_or(ENODEV)?;
|
||
let handle = iface.sockets().lock_no_preempt().add(socket);
|
||
// log::debug!("Bind to iface: {}", iface.iface_name());
|
||
// return Ok(Self { inner: vec![(handle, iface)] });
|
||
return Ok(Self { handle, iface });
|
||
}
|
||
}
|
||
|
||
pub fn bind_ephemeral<T>(
|
||
socket: T,
|
||
// socket_type: Types,
|
||
remote: smoltcp::wire::IpAddress,
|
||
) -> Result<(Self, smoltcp::wire::IpAddress), SystemError>
|
||
where
|
||
T: smoltcp::socket::AnySocket<'static>,
|
||
{
|
||
let (iface, address) = get_ephemeral_iface(&remote);
|
||
// let bound_port = iface.port_manager().bind_ephemeral_port(socket_type)?;
|
||
let handle = iface.sockets().lock_no_preempt().add(socket);
|
||
// let endpoint = smoltcp::wire::IpEndpoint::new(local_addr, bound_port);
|
||
Ok((Self { handle, iface }, address))
|
||
}
|
||
|
||
pub fn port_manager(&self) -> &PortManager {
|
||
self.iface.port_manager()
|
||
}
|
||
|
||
pub fn with_mut<T: smoltcp::socket::AnySocket<'static>, R, F: FnMut(&mut T) -> R>(
|
||
&self,
|
||
mut f: F,
|
||
) -> R {
|
||
f(self.iface.sockets().lock().get_mut::<T>(self.handle))
|
||
}
|
||
|
||
pub fn with<T: smoltcp::socket::AnySocket<'static>, R, F: Fn(&T) -> R>(&self, f: F) -> R {
|
||
f(self.iface.sockets().lock().get::<T>(self.handle))
|
||
}
|
||
|
||
pub fn iface(&self) -> &Arc<dyn Iface> {
|
||
&self.iface
|
||
}
|
||
|
||
pub fn release(&self) {
|
||
self.iface.sockets().lock().remove(self.handle);
|
||
}
|
||
}
|
||
|
||
#[inline]
|
||
pub fn get_iface_to_bind(ip_addr: &smoltcp::wire::IpAddress) -> Option<Arc<dyn Iface>> {
|
||
// log::debug!("get_iface_to_bind: {:?}", ip_addr);
|
||
// if ip_addr.is_unspecified()
|
||
crate::net::NET_DEVICES
|
||
.read_irqsave()
|
||
.iter()
|
||
.find(|(_, iface)| {
|
||
let guard = iface.smol_iface().lock();
|
||
// log::debug!("iface name: {}, ip: {:?}", iface.iface_name(), guard.ip_addrs());
|
||
return guard.has_ip_addr(*ip_addr);
|
||
})
|
||
.map(|(_, iface)| iface.clone())
|
||
}
|
||
|
||
/// Get a suitable iface to deal with sendto/connect request if the socket is not bound to an iface.
|
||
/// If the remote address is the same as that of some iface, we will use the iface.
|
||
/// Otherwise, we will use a default interface.
|
||
fn get_ephemeral_iface(
|
||
remote_ip_addr: &smoltcp::wire::IpAddress,
|
||
) -> (Arc<dyn Iface>, smoltcp::wire::IpAddress) {
|
||
get_iface_to_bind(remote_ip_addr)
|
||
.map(|iface| (iface, *remote_ip_addr))
|
||
.or({
|
||
let ifaces = NET_DEVICES.read_irqsave();
|
||
ifaces.iter().find_map(|(_, iface)| {
|
||
iface
|
||
.smol_iface()
|
||
.lock()
|
||
.ip_addrs()
|
||
.iter()
|
||
.find(|cidr| cidr.contains_addr(remote_ip_addr))
|
||
.map(|cidr| (iface.clone(), cidr.address()))
|
||
})
|
||
})
|
||
.or({
|
||
NET_DEVICES.read_irqsave().values().next().map(|iface| {
|
||
(
|
||
iface.clone(),
|
||
iface.smol_iface().lock().ip_addrs()[0].address(),
|
||
)
|
||
})
|
||
})
|
||
.expect("No network interface")
|
||
}
|