Merge pull request #251 from rcore-os/mergeBranch

Initially add socket syscall function
This commit is contained in:
chyyuu 2021-12-28 23:24:25 +08:00 committed by GitHub
commit 4aedfd4005
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 2204 additions and 25 deletions

View File

@ -23,7 +23,8 @@ device_tree = { git = "https://github.com/rcore-os/device_tree-rs", rev = "2f2e5
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "b3f9f51" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2aaf7d6", optional = true }
rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-features = false, rev = "ca5b1bc", optional = true }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp"] }
# smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp"] }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
[target.'cfg(not(target_os = "none"))'.dependencies]
async-std = { version = "1.10", optional = true }

View File

@ -0,0 +1,60 @@
// smoltcp
use smoltcp::{iface::Interface, phy::Loopback, time::Instant};
use crate::net::get_sockets;
use alloc::sync::Arc;
use alloc::string::String;
use spin::Mutex;
use crate::scheme::{NetScheme, Scheme};
use crate::{DeviceError, DeviceResult};
use alloc::vec::Vec;
use smoltcp::wire::EthernetAddress;
use smoltcp::wire::IpCidr;
#[derive(Clone)]
pub struct LoopbackInterface {
pub iface: Arc<Mutex<Interface<'static, Loopback>>>,
pub name: String,
}
impl Scheme for LoopbackInterface {
fn name(&self) -> &str {
"loopback"
}
fn handle_irq(&self, _cause: usize) {}
}
impl NetScheme for LoopbackInterface {
fn recv(&self, _buf: &mut [u8]) -> DeviceResult<usize> {
unimplemented!()
}
fn send(&self, _buf: &[u8]) -> DeviceResult<usize> {
unimplemented!()
}
fn poll(&self) -> DeviceResult {
let timestamp = Instant::from_millis(0);
let sockets = get_sockets();
let mut sockets = sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => Ok(()),
Err(err) => {
debug!("poll got err {}", err);
Err(DeviceError::IoError)
}
}
}
fn get_mac(&self) -> EthernetAddress {
unimplemented!()
}
fn get_ifname(&self) -> String {
unimplemented!()
}
fn get_ip_addrrs(&self) -> Vec<IpCidr> {
unimplemented!()
}
}

View File

@ -57,3 +57,21 @@ pub const PAGE_SIZE: usize = 4096;
type VirtAddr = usize;
type PhysAddr = usize;
pub mod loopback;
pub use loopback::LoopbackInterface;
use alloc::sync::Arc;
use alloc::vec;
use spin::Mutex;
use smoltcp::socket::SocketSet;
lazy_static::lazy_static! {
pub static ref SOCKETS: Arc<Mutex<SocketSet<'static>>> =
Arc::new(Mutex::new(SocketSet::new(vec![])));
}
pub fn get_sockets() -> Arc<Mutex<SocketSet<'static>>> {
SOCKETS.clone()
}

View File

@ -64,8 +64,6 @@ impl Scheme for RTLxInterface {
//return true;
return;
}
return;
}
}
@ -110,7 +108,7 @@ impl NetScheme for RTLxInterface {
fn send(&self, data: &[u8]) -> DeviceResult<usize> {
if self.driver.0.lock().can_send() {
self.driver.0.lock().geth_send(&data).unwrap();
self.driver.0.lock().geth_send(data).unwrap();
Ok(data.len())
} else {
Err(DeviceError::NotReady)
@ -205,7 +203,7 @@ pub fn rtlx_init<F: Fn(usize, usize) -> Option<usize>>(
info!("rtl8211f interface up with addr 192.168.0.123/24");
let rtl8211f_iface = RTLxInterface {
iface: Arc::new(Mutex::new(iface)),
driver: net_driver.clone(),
driver: net_driver,
name: String::from("rtl8211f"),
irq,
};

View File

@ -23,6 +23,8 @@ git-version = "0.3"
numeric-enum-macro = "0.2"
lazy_static = { version = "1.4", features = ["spin_no_std"] }
zcore-drivers = { path = "../drivers", features = ["virtio"] }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]

View File

@ -1,5 +1,6 @@
//! Bootstrap and initialization.
use super::net;
use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
hal_fn_impl! {
@ -23,6 +24,7 @@ hal_fn_impl! {
info!("Primary CPU {} init...", crate::cpu::cpu_id());
unsafe { trapframe::init() };
super::arch::primary_init();
net::init();
}
fn secondary_init() {

View File

@ -11,6 +11,7 @@ cfg_if! {
pub mod boot;
pub mod mem;
pub mod net;
pub mod thread;
pub mod timer;

View File

@ -0,0 +1,70 @@
use smoltcp::{
iface::{InterfaceBuilder, NeighborCache, Route, Routes},
phy::{Loopback, Medium},
wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address},
};
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
// use zcore_drivers::net::get_sockets;
use alloc::sync::Arc;
use alloc::string::String;
use spin::Mutex;
use crate::drivers::add_device;
use crate::drivers::all_net;
use zcore_drivers::net::LoopbackInterface;
use zcore_drivers::scheme::NetScheme;
use zcore_drivers::Device;
pub fn init() {
let name = String::from("loopback");
warn!("name : {}", name);
// 初始化 一个 协议栈
// 从外界 接受 一些 配置 参数 如果 没有 选择 默认 的
// 网络 设备
// 默认 loopback
let loopback = Loopback::new(Medium::Ethernet);
// 为 设备 分配 网络 身份
// 物理地址
let mac: [u8; 6] = [0x52, 0x54, 0x98, 0x76, 0x54, 0x32];
let ethernet_addr = EthernetAddress::from_bytes(&mac);
// ip 地址
let ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 24)];
// qemu
// let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
// 路由
let default_gateway = Ipv4Address::new(127, 0, 0, 1);
// qemu route
// let default_gateway = Ipv4Address::new(10, 0, 2, 2);
static mut ROUTES_STORAGE: [Option<(IpCidr, Route)>; 1] = [None; 1];
let mut routes = unsafe { Routes::new(&mut ROUTES_STORAGE[..]) };
routes.add_default_ipv4_route(default_gateway).unwrap();
// arp缓存
let neighbor_cache = NeighborCache::new(BTreeMap::new());
// 设置 主要 设置 iface
let iface = InterfaceBuilder::new(loopback)
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.routes(routes)
.neighbor_cache(neighbor_cache)
.finalize();
let loopback_iface = LoopbackInterface {
iface: Arc::new(Mutex::new(iface)),
name,
};
// loopback_iface
let dev = Device::Net(Arc::new(loopback_iface));
add_device(dev);
}
pub fn get_net_device() -> Vec<Arc<dyn NetScheme>> {
all_net().as_vec().clone()
}

View File

@ -1,5 +1,6 @@
//! Bootstrap and initialization.
use super::net;
use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
hal_fn_impl! {
@ -17,6 +18,8 @@ hal_fn_impl! {
unsafe {
super::macos::register_sigsegv_handler();
}
net::init();
}
}
}

View File

@ -6,6 +6,7 @@ pub mod boot;
pub mod config;
pub mod cpu;
pub mod mem;
pub mod net;
pub mod thread;
pub mod timer;
pub mod vdso;

View File

@ -0,0 +1,70 @@
use smoltcp::{
iface::{InterfaceBuilder, NeighborCache, Route, Routes},
phy::{Loopback, Medium},
wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address},
};
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
// use zcore_drivers::net::get_sockets;
use alloc::sync::Arc;
use alloc::string::String;
use spin::Mutex;
use crate::drivers::add_device;
use crate::drivers::all_net;
use zcore_drivers::net::LoopbackInterface;
use zcore_drivers::scheme::NetScheme;
use zcore_drivers::Device;
pub fn init() {
let name = String::from("loopback");
warn!("name : {}", name);
// 初始化 一个 协议栈
// 从外界 接受 一些 配置 参数 如果 没有 选择 默认 的
// 网络 设备
// 默认 loopback
let loopback = Loopback::new(Medium::Ethernet);
// 为 设备 分配 网络 身份
// 物理地址
let mac: [u8; 6] = [0x52, 0x54, 0x98, 0x76, 0x54, 0x32];
let ethernet_addr = EthernetAddress::from_bytes(&mac);
// ip 地址
let ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 24)];
// qemu
// let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
// 路由
let default_gateway = Ipv4Address::new(127, 0, 0, 1);
// qemu route
// let default_gateway = Ipv4Address::new(10, 0, 2, 2);
static mut ROUTES_STORAGE: [Option<(IpCidr, Route)>; 1] = [None; 1];
let mut routes = unsafe { Routes::new(&mut ROUTES_STORAGE[..]) };
routes.add_default_ipv4_route(default_gateway).unwrap();
// arp缓存
let neighbor_cache = NeighborCache::new(BTreeMap::new());
// 设置 主要 设置 iface
let iface = InterfaceBuilder::new(loopback)
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.routes(routes)
.neighbor_cache(neighbor_cache)
.finalize();
let loopback_iface = LoopbackInterface {
iface: Arc::new(Mutex::new(iface)),
name,
};
// loopback_iface
let dev = Device::Net(Arc::new(loopback_iface));
add_device(dev);
}
pub fn get_net_device() -> Vec<Arc<dyn NetScheme>> {
all_net().as_vec().clone()
}

View File

@ -25,3 +25,5 @@ rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7c232ec"
rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7c232ec" }
rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7c232ec" }
cfg-if = "1.0"
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
zcore-drivers = { path = "../drivers", features = ["virtio"] }

View File

@ -5,6 +5,7 @@
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::uninit_vec)]
#![feature(bool_to_option)]
#![feature(untagged_unions)]
#[macro_use]
extern crate alloc;
@ -21,6 +22,7 @@ pub mod fs;
// layer 2
pub mod ipc;
pub mod loader;
pub mod net;
pub mod process;
pub mod signal;
pub mod sync;

304
linux-object/src/net/mod.rs Normal file
View File

@ -0,0 +1,304 @@
//! Linux socket objects
//!
/// missing documentation
pub mod socket_address;
pub use socket_address::*;
/// missing documentation
pub mod tcp;
pub use tcp::*;
/// missing documentation
pub mod udp;
pub use udp::*;
use spin::Mutex;
/// missing documentation
// pub mod raw;
// pub use raw::*;
/// missing documentation
// pub mod icmp;
// pub use icmp::*;
// pub mod stack;
// ============= Socket Set =============
use zcore_drivers::net::get_sockets;
// lazy_static! {
// /// Global SocketSet in smoltcp.
// ///
// /// Because smoltcp is a single thread network stack,
// /// every socket operation needs to lock this.
// pub static ref SOCKETS: Mutex<SocketSet<'static>> =
// Mutex::new(SocketSet::new(vec![]));
// }
// ============= Socket Set =============
// ============= Define =============
// ========TCP
/// missing documentation
pub const TCP_SENDBUF: usize = 512 * 1024; // 512K
/// missing documentation
pub const TCP_RECVBUF: usize = 512 * 1024; // 512K
// ========UDP
/// missing documentation
pub const UDP_METADATA_BUF: usize = 1024;
/// missing documentation
pub const UDP_SENDBUF: usize = 64 * 1024; // 64K
/// missing documentation
pub const UDP_RECVBUF: usize = 64 * 1024; // 64K
// ========RAW
/// missing documentation
pub const RAW_METADATA_BUF: usize = 1024;
/// missing documentation
pub const RAW_SENDBUF: usize = 64 * 1024; // 64K
/// missing documentation
pub const RAW_RECVBUF: usize = 64 * 1024; // 64K
// ========RAW
/// missing documentation
pub const ICMP_METADATA_BUF: usize = 1024;
/// missing documentation
pub const ICMP_SENDBUF: usize = 64 * 1024; // 64K
/// missing documentation
pub const ICMP_RECVBUF: usize = 64 * 1024; // 64K
// ========Other
/// missing documentation
pub const IPPROTO_IP: usize = 0;
/// missing documentation
pub const IP_HDRINCL: usize = 3;
// ============= Define =============
// ============= SocketHandle =============
use smoltcp::socket::SocketHandle;
/// A wrapper for `SocketHandle`.
/// Auto increase and decrease reference count on Clone and Drop.
#[derive(Debug)]
struct GlobalSocketHandle(SocketHandle);
impl Clone for GlobalSocketHandle {
fn clone(&self) -> Self {
get_sockets().lock().retain(self.0);
Self(self.0)
}
}
impl Drop for GlobalSocketHandle {
fn drop(&mut self) {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
sockets.release(self.0);
sockets.prune();
// send FIN immediately when applicable
drop(sockets);
poll_ifaces();
}
}
// #[cfg(feature = "e1000")]
use kernel_hal::net::get_net_device;
#[cfg(feature = "loopback")]
use hashbrown::HashMap;
#[cfg(feature = "loopback")]
use kernel_hal::timer_now;
// #[cfg(feature = "loopback")]
// use net_stack::{NetStack, NET_STACK};
#[cfg(feature = "loopback")]
use smoltcp::time::Instant;
// /// miss doc
// #[cfg(feature = "loopback")]
// pub fn get_net_stack() -> HashMap<usize, Arc<dyn NetStack>> {
// NET_STACK.read().clone()
// }
/// miss doc
fn poll_ifaces() {
for iface in get_net_device().iter() {
match iface.poll() {
Ok(_) => {}
Err(e) => {
warn!("error : {:?}", e)
}
}
}
}
// use core::future::Future;
// use core::pin::Pin;
// use core::task::Context;
// use core::task::Poll;
// use smoltcp::socket::TcpSocket;
// ============= SocketHandle =============
// ============= Endpoint =============
use smoltcp::wire::IpEndpoint;
/// missing documentation
#[derive(Clone, Debug)]
pub enum Endpoint {
/// missing documentation
Ip(IpEndpoint),
/// missing documentation
LinkLevel(LinkLevelEndpoint),
/// missing documentation
Netlink(NetlinkEndpoint),
}
/// missing documentation
#[derive(Clone, Debug)]
pub struct LinkLevelEndpoint {
/// missing documentation
pub interface_index: usize,
}
impl LinkLevelEndpoint {
/// missing documentation
pub fn new(ifindex: usize) -> Self {
LinkLevelEndpoint {
interface_index: ifindex,
}
}
}
/// missing documentation
#[derive(Clone, Debug)]
pub struct NetlinkEndpoint {
/// missing documentation
pub port_id: u32,
/// missing documentation
pub multicast_groups_mask: u32,
}
impl NetlinkEndpoint {
/// missing documentation
pub fn new(port_id: u32, multicast_groups_mask: u32) -> Self {
NetlinkEndpoint {
port_id,
multicast_groups_mask,
}
}
}
// ============= Endpoint =============
// ============= Rand Port =============
/// !!!! need riscv rng
pub fn rand() -> u64 {
// use core::arch::x86_64::_rdtsc;
// rdrand is not implemented in QEMU
// so use rdtsc instead
10000
}
#[allow(unsafe_code)]
/// missing documentation
fn get_ephemeral_port() -> u16 {
// TODO selects non-conflict high port
static mut EPHEMERAL_PORT: u16 = 0;
unsafe {
if EPHEMERAL_PORT == 0 {
EPHEMERAL_PORT = (49152 + rand() % (65536 - 49152)) as u16;
}
if EPHEMERAL_PORT == 65535 {
EPHEMERAL_PORT = 49152;
} else {
EPHEMERAL_PORT += 1;
}
EPHEMERAL_PORT
}
}
// ============= Rand Port =============
// ============= Util =============
#[allow(unsafe_code)]
/// # Safety
/// Convert C string to Rust string
pub unsafe fn from_cstr(s: *const u8) -> &'static str {
use core::{slice, str};
let len = (0usize..).find(|&i| *s.add(i) == 0).unwrap();
str::from_utf8(slice::from_raw_parts(s, len)).unwrap()
}
// ============= Util =============
use crate::error::*;
use alloc::boxed::Box;
use alloc::fmt::Debug;
use alloc::sync::Arc;
use async_trait::async_trait;
// use core::ops::{Deref, DerefMut};
/// Common methods that a socket must have
#[async_trait]
pub trait Socket: Send + Sync + Debug {
/// missing documentation
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint);
/// missing documentation
fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult;
/// missing documentation
fn poll(&self) -> (bool, bool, bool); // (in, out, err)
/// missing documentation
async fn connect(&self, endpoint: Endpoint) -> SysResult;
/// missing documentation
fn bind(&mut self, _endpoint: Endpoint) -> SysResult {
Err(LxError::EINVAL)
}
/// missing documentation
fn listen(&mut self) -> SysResult {
Err(LxError::EINVAL)
}
/// missing documentation
fn shutdown(&self) -> SysResult {
Err(LxError::EINVAL)
}
/// missing documentation
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
Err(LxError::EINVAL)
}
/// missing documentation
fn endpoint(&self) -> Option<Endpoint> {
None
}
/// missing documentation
fn remote_endpoint(&self) -> Option<Endpoint> {
None
}
/// missing documentation
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
warn!("setsockopt is unimplemented");
Ok(0)
}
/// missing documentation
fn ioctl(&self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
warn!("ioctl is unimplemented for this socket");
Ok(0)
}
/// missing documentation
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
warn!("ioctl is unimplemented for this socket");
Ok(0)
}
}

View File

@ -0,0 +1,304 @@
// core
use core::cmp::min;
use core::mem::size_of;
// crate
use crate::error::LxError;
use crate::net::Endpoint;
// smoltcp
pub use smoltcp::wire::{IpAddress, Ipv4Address};
// #
use crate::net::*;
use kernel_hal::user::{UserInOutPtr, UserOutPtr};
// use numeric_enum_macro::numeric_enum;
/// missing documentation
#[repr(C)]
pub union SockAddr {
/// missing documentation
pub family: u16,
/// missing documentation
pub addr_in: SockAddrIn,
/// missing documentation
pub addr_un: SockAddrUn,
/// missing documentation
pub addr_ll: SockAddrLl,
/// missing documentation
pub addr_nl: SockAddrNl,
/// missing documentation
pub addr_ph: SockAddrPlaceholder,
}
/// missing documentation
#[repr(C)]
pub struct SockAddrIn {
/// missing documentation
pub sin_family: u16,
/// missing documentation
pub sin_port: u16,
/// missing documentation
pub sin_addr: u32,
/// missing documentation
pub sin_zero: [u8; 8],
}
/// missing documentation
#[repr(C)]
pub struct SockAddrUn {
/// missing documentation
pub sun_family: u16,
/// missing documentation
pub sun_path: [u8; 108],
}
/// missing documentation
#[repr(C)]
pub struct SockAddrLl {
/// missing documentation
pub sll_family: u16,
/// missing documentation
pub sll_protocol: u16,
/// missing documentation
pub sll_ifindex: u32,
/// missing documentation
pub sll_hatype: u16,
/// missing documentation
pub sll_pkttype: u8,
/// missing documentation
pub sll_halen: u8,
/// missing documentation
pub sll_addr: [u8; 8],
}
/// missing documentation
#[repr(C)]
pub struct SockAddrNl {
nl_family: u16,
nl_pad: u16,
nl_pid: u32,
nl_groups: u32,
}
/// missing documentation
#[repr(C)]
pub struct SockAddrPlaceholder {
/// missing documentation
pub family: u16,
/// missing documentation
pub data: [u8; 14],
}
impl From<Endpoint> for SockAddr {
fn from(endpoint: Endpoint) -> Self {
#[allow(warnings)]
if let Endpoint::Ip(ip) = endpoint {
match ip.addr {
IpAddress::Ipv4(ipv4) => SockAddr {
addr_in: SockAddrIn {
sin_family: AddressFamily::Internet.into(),
sin_port: u16::to_be(ip.port),
sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)),
sin_zero: [0; 8],
},
},
IpAddress::Unspecified => SockAddr {
addr_ph: SockAddrPlaceholder {
family: AddressFamily::Unspecified.into(),
data: [0; 14],
},
},
_ => unimplemented!("only ipv4"),
}
// unix socket 暂时 未开启
// } else if let Endpoint::LinkLevel(link_level) = endpoint {
// SockAddr {
// addr_ll: SockAddrLl {
// sll_family: AddressFamily::Packet.into(),
// sll_protocol: 0,
// sll_ifindex: link_level.interface_index as u32,
// sll_hatype: 0,
// sll_pkttype: 0,
// sll_halen: 0,
// sll_addr: [0; 8],
// },
// }
// } else if let Endpoint::Netlink(netlink) = endpoint {
// SockAddr {
// addr_nl: SockAddrNl {
// nl_family: AddressFamily::Netlink.into(),
// nl_pad: 0,
// nl_pid: netlink.port_id,
// nl_groups: netlink.multicast_groups_mask,
// },
// }
} else {
unimplemented!("only ip");
}
}
}
/// missing documentation
pub fn sockaddr_to_endpoint(addr: SockAddr, len: usize) -> Result<Endpoint, LxError> {
if len < size_of::<u16>() {
return Err(LxError::EINVAL);
}
// let addr = unsafe { vm.check_read_ptr(addr)? };
if len < addr.len()? {
return Err(LxError::EINVAL);
}
#[allow(unsafe_code)]
unsafe {
match AddressFamily::from(addr.family) {
AddressFamily::Internet => {
let port = u16::from_be(addr.addr_in.sin_port);
let addr = IpAddress::from(Ipv4Address::from_bytes(
&u32::from_be(addr.addr_in.sin_addr).to_be_bytes()[..],
));
Ok(Endpoint::Ip((addr, port).into()))
}
AddressFamily::Unix => Err(LxError::EINVAL),
// AddressFamily::Packet => Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
// addr.addr_ll.sll_ifindex as usize,
// ))),
// AddressFamily::Netlink => Ok(Endpoint::Netlink(NetlinkEndpoint::new(
// addr.addr_nl.nl_pid,
// addr.addr_nl.nl_groups,
// ))),
_ => Err(LxError::EINVAL),
}
}
}
impl SockAddr {
fn len(&self) -> Result<usize, LxError> {
#[allow(unsafe_code)]
match AddressFamily::from(unsafe { self.family }) {
AddressFamily::Internet => Ok(size_of::<SockAddrIn>()),
AddressFamily::Packet => Ok(size_of::<SockAddrLl>()),
AddressFamily::Netlink => Ok(size_of::<SockAddrNl>()),
AddressFamily::Unix => Err(LxError::EINVAL),
_ => Err(LxError::EINVAL),
}
}
/// # Safety
/// Write to user sockaddr
/// Check mutability for user
#[allow(dead_code)]
pub fn write_to(
self,
addr: UserOutPtr<SockAddr>,
mut addr_len: UserInOutPtr<u32>,
) -> SysResult {
// Ignore NULL
if addr.is_null() {
return Ok(0);
}
let max_addr_len = addr_len.read()? as usize;
let full_len = self.len()?;
let written_len = min(max_addr_len, full_len);
if written_len > 0 {
#[allow(unsafe_code)]
let source = unsafe {
core::slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len)
};
#[allow(unsafe_code)]
let mut addr: UserOutPtr<u8> = unsafe { core::mem::transmute(addr) };
addr.write_array(source)?;
}
addr_len.write(full_len as u32)?;
Ok(0)
}
}
macro_rules! enum_with_unknown {
(
$( #[$enum_attr:meta] )*
pub enum $name:ident($ty:ty) {
$( $variant:ident = $value:expr ),+ $(,)*
}
) => {
enum_with_unknown! {
$( #[$enum_attr] )*
pub doc enum $name($ty) {
$( #[doc(shown)] $variant = $value ),+
}
}
};
(
$( #[$enum_attr:meta] )*
pub doc enum $name:ident($ty:ty) {
$(
$( #[$variant_attr:meta] )+
$variant:ident = $value:expr $(,)*
),+
}
) => {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
$( #[$enum_attr] )*
pub enum $name {
$(
$( #[$variant_attr] )*
$variant
),*,
/// missing documentation
Unknown($ty)
}
impl ::core::convert::From<$ty> for $name {
fn from(value: $ty) -> Self {
match value {
$( $value => $name::$variant ),*,
other => $name::Unknown(other)
}
}
}
impl ::core::convert::From<$name> for $ty {
fn from(value: $name) -> Self {
match value {
$( $name::$variant => $value ),*,
$name::Unknown(other) => other
}
}
}
}
}
enum_with_unknown! {
/// Address families
pub doc enum AddressFamily(u16) {
/// Unspecified
Unspecified = 0,
/// Unix domain sockets
Unix = 1,
/// Internet IP Protocol
Internet = 2,
/// Netlink
Netlink = 16,
/// Packet family
Packet = 17,
}
}
/// missing documentation
#[repr(C)]
pub struct ArpReq {
/// missing documentation
pub arp_pa: SockAddrPlaceholder,
/// missing documentation
pub arp_ha: SockAddrPlaceholder,
/// missing documentation
pub arp_flags: u32,
/// missing documentation
pub arp_netmask: SockAddrPlaceholder,
/// missing documentation
pub arp_dev: [u8; 16],
}

667
linux-object/src/net/tcp.rs Normal file
View File

@ -0,0 +1,667 @@
// Tcpsocket
#![allow(dead_code)]
// crate
use crate::error::LxError;
use crate::error::LxResult;
use crate::net::get_ephemeral_port;
use crate::net::get_sockets;
// use crate::net::get_net_device;
use crate::net::poll_ifaces;
use crate::net::Endpoint;
use crate::net::GlobalSocketHandle;
use crate::net::IpEndpoint;
use crate::net::Socket;
use crate::net::SysResult;
use crate::net::TCP_RECVBUF;
use crate::net::TCP_SENDBUF;
use alloc::sync::Arc;
use spin::Mutex;
// alloc
use alloc::boxed::Box;
use alloc::vec;
// smoltcp
use smoltcp::socket::TcpSocket;
use smoltcp::socket::TcpSocketBuffer;
// async
use async_trait::async_trait;
// third part
#[allow(unused_imports)]
use zircon_object::object::*;
/// missing documentation
#[derive(Debug)]
pub struct TcpSocketState {
/// missing documentation
// base: KObjectBase,
/// missing documentation
handle: GlobalSocketHandle,
/// missing documentation
local_endpoint: Option<IpEndpoint>, // save local endpoint for bind()
/// missing documentation
is_listening: bool,
}
impl Default for TcpSocketState {
fn default() -> Self {
TcpSocketState::new()
}
}
impl TcpSocketState {
/// missing documentation
pub fn new() -> Self {
let rx_buffer = TcpSocketBuffer::new(vec![0; TCP_RECVBUF]);
let tx_buffer = TcpSocketBuffer::new(vec![0; TCP_SENDBUF]);
let socket = TcpSocket::new(rx_buffer, tx_buffer);
let handle = GlobalSocketHandle(get_sockets().lock().add(socket));
TcpSocketState {
// base: KObjectBase::new(),
handle,
local_endpoint: None,
is_listening: false,
}
}
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (LxResult<usize>, Endpoint) {
warn!("tcp read");
loop {
poll_ifaces();
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.may_recv() {
if let Ok(size) = socket.recv_slice(data) {
if size > 0 {
let endpoint = socket.remote_endpoint();
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
return (Ok(size), Endpoint::Ip(endpoint));
}
}
} else {
return (
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
);
}
}
}
/// missing documentation
#[cfg(feature = "e1000")]
pub async fn read(&self, data: &mut [u8]) -> (LxResult<usize>, Endpoint) {
warn!("tcp read");
use core::task::Poll;
futures::future::poll_fn(|cx| {
self.with(|s| {
if s.can_recv() {
warn!("can recv ok");
if let Ok(size) = s.recv_slice(data) {
warn!("--------------Ok size {}", size);
if size > 0 {
let endpoint = s.remote_endpoint();
Poll::Ready((Ok(size), Endpoint::Ip(endpoint)))
} else {
warn!("wait size > 0");
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
} else {
warn!("recv_slice not Oksize");
Poll::Ready((
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
))
}
} else {
error!("can not recv");
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
})
})
.await
// let net_sockets = get_net_sockets();
// let mut sockets = net_sockets.lock();
// let mut socket = sockets.get::<TcpSocket>(self.handle.0);
// // if socket.may_recv() {
// if let Ok(size) = socket.recv_slice(data) {
// let endpoint = socket.remote_endpoint();
// return (Ok(size), Endpoint::Ip(endpoint));
// } else {
// return (
// Err(LxError::ENOTCONN),
// Endpoint::Ip(IpEndpoint::UNSPECIFIED),
// );
// }
}
/// missing documentation
pub fn write(&self, data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
warn!("tcp write");
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.is_open() {
if socket.can_send() {
match socket.send_slice(data) {
Ok(size) => {
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
Ok(size)
}
Err(_) => Err(LxError::ENOBUFS),
}
} else {
Err(LxError::ENOBUFS)
}
} else {
Err(LxError::ENOTCONN)
}
}
/// missing documentation
fn poll(&self) -> (bool, bool, bool) {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
let (mut input, mut output, mut err) = (false, false, false);
if self.is_listening && socket.is_active() {
// a new connection
input = true;
} else if !socket.is_open() {
err = true;
} else {
if socket.can_recv() {
input = true;
}
if socket.can_send() {
output = true;
}
}
(input, output, err)
}
/// missing documentation
pub async fn connect(&self, endpoint: Endpoint) -> SysResult {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
#[allow(warnings)]
if let Endpoint::Ip(ip) = endpoint {
let local_port = get_ephemeral_port();
socket
.connect(ip, local_port)
.map_err(|_| LxError::ENOBUFS)?;
// avoid deadlock
drop(socket);
drop(sockets);
// wait for connection result
loop {
poll_ifaces();
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
use smoltcp::socket::TcpState;
match socket.state() {
TcpState::SynSent => {
// still connecting
drop(socket);
drop(sockets);
poll_ifaces();
}
TcpState::Established => {
break Ok(0);
}
_ => {
break Err(LxError::ECONNREFUSED);
}
}
}
} else {
drop(socket);
drop(sockets);
Err(LxError::EINVAL)
}
}
/// missing documentation
#[cfg(feature = "e1000")]
pub async fn connect(&self, endpoint: Endpoint) -> SysResult {
warn!("tcp connect");
// if let Endpoint::Ip(ip) = endpoint {
// let local_port = get_ephemeral_port();
// self.with(|ss| ss.connect(ip, local_port).map_err(|_| LxError::ENOBUFS))?;
// // use crate::net::IFaceFuture;
// // IFaceFuture { flag: false }.await;
// // warn!("no");
// // use smoltcp::socket::TcpState;
// // let ret = self.with(|ss| match ss.state() {
// // TcpState::SynSent => {
// // // still connecting
// // warn!("SynSent");
// // Ok(0)
// // }
// // TcpState::Established => Ok(0),
// // _ => Err(LxError::ECONNREFUSED),
// // });
// // Ok(0)
// // socket
// // .connect(ip, local_port)
// // .map_err(|_| LxError::ENOBUFS)?;
// // use crate::net::ConnectFuture;
// // use smoltcp::socket::SocketRef;
// // let c = ConnectFuture {
// // socket: SocketRef::into_inner(socket),
// // }
// // .await;
// // drop(c);
// // use core::future::Future;
// // use core::pin::Pin;
// // use core::task::Context;
// use crate::net::IFaceFuture;
// IFaceFuture.await;
// // warn!("no");
// // IFaceFuture.await;
// // warn!("no");
// // IFaceFuture.await;
// // warn!("no");
// // IFaceFuture.await;
// // warn!("no");
// use core::task::Poll;
// use smoltcp::socket::TcpState;
// let ret = futures::future::poll_fn(|cx| {
// self.with(|s| {
// // s.connect(ip, local_port).map_err(|_| LxError::ENOBUFS)?;
// match s.state() {
// TcpState::Closed | TcpState::TimeWait => {
// warn!("Closed|TimeWait");
// Poll::Ready(Err(LxError::ECONNREFUSED))
// }
// TcpState::Listen => {
// warn!("Listen");
// Poll::Ready(Err(LxError::ECONNREFUSED))
// }
// TcpState::SynSent => {
// warn!("SynSent");
// s.register_recv_waker(cx.waker());
// s.register_send_waker(cx.waker());
// // drop(s);
// // #[cfg(feature = "e1000")]
// // poll_ifaces_e1000();
// // IFaceFuture.await
// Poll::Pending
// }
// TcpState::SynReceived => {
// warn!("SynReceived");
// s.register_recv_waker(cx.waker());
// s.register_send_waker(cx.waker());
// Poll::Pending
// }
// TcpState::Established => {
// warn!("Established");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// // TcpState::TimeWait => {
// // warn!("TimeWait");
// // // s.register_recv_waker(cx.waker());
// // // s.register_send_waker(cx.waker());
// // Poll::Ready(Ok(0))
// // // Poll::Pending
// // }
// TcpState::FinWait1 => {
// warn!("------------------------------------FinWait1");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// TcpState::FinWait2 => {
// warn!("----------------------------------------FinWait2");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// TcpState::Closing => {
// warn!("-------------------------------------------Closing");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// TcpState::LastAck => {
// warn!("-------------------------------------------LastAck");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// _ => {
// warn!("_");
// Poll::Ready(Err(LxError::ECONNREFUSED))
// }
// }
// })
// })
// .await;
// // #[cfg(feature = "e1000")]
// // poll_ifaces_e1000();
// IFaceFuture.await;
// warn!("ret {:?}", ret);
// ret
// // Ok(0)
// } else {
// return Err(LxError::EINVAL);
// }
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
#[allow(warnings)]
if let Endpoint::Ip(ip) = endpoint {
let local_port = get_ephemeral_port();
socket
.connect(ip, local_port)
.map_err(|_| LxError::ENOBUFS)?;
// avoid deadlock
drop(socket);
drop(sockets);
#[cfg(feature = "e1000")]
poll_ifaces_e1000();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
// wait for connection result
loop {
warn!("loop");
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
use smoltcp::socket::TcpState;
match socket.state() {
TcpState::SynSent => {
// still connecting
warn!("SynSent");
drop(socket);
drop(sockets);
#[cfg(feature = "e1000")]
poll_ifaces_e1000();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
}
TcpState::Established => {
warn!("estab");
break Ok(0);
}
_ => {
break Err(LxError::ECONNREFUSED);
}
}
}
} else {
drop(socket);
drop(sockets);
return Err(LxError::EINVAL);
}
}
/// missing documentation
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
if let Endpoint::Ip(mut ip) = endpoint {
if ip.port == 0 {
ip.port = get_ephemeral_port();
}
self.local_endpoint = Some(ip);
self.is_listening = false;
Ok(0)
} else {
Err(LxError::EINVAL)
}
}
/// missing documentation
fn listen(&mut self) -> SysResult {
if self.is_listening {
// it is ok to listen twice
return Ok(0);
}
let local_endpoint = self.local_endpoint.ok_or(LxError::EINVAL)?;
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
info!("socket listening on {:?}", local_endpoint);
if socket.is_listening() {
return Ok(0);
}
match socket.listen(local_endpoint) {
Ok(()) => {
self.is_listening = true;
Ok(0)
}
Err(_) => Err(LxError::EINVAL),
}
}
/// missing documentation
fn shutdown(&self) -> SysResult {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
socket.close();
Ok(0)
}
/// missing documentation
async fn accept(&mut self) -> Result<(Arc<Mutex<dyn Socket>>, Endpoint), LxError> {
let endpoint = self.local_endpoint.ok_or(LxError::EINVAL)?;
loop {
poll_ifaces();
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.is_active() {
let remote_endpoint = socket.remote_endpoint();
drop(socket);
let new_socket = {
let rx_buffer = TcpSocketBuffer::new(vec![0; TCP_RECVBUF]);
let tx_buffer = TcpSocketBuffer::new(vec![0; TCP_SENDBUF]);
let mut socket = TcpSocket::new(rx_buffer, tx_buffer);
socket.listen(endpoint).unwrap();
let new_handle = GlobalSocketHandle(sockets.add(socket));
let old_handle = ::core::mem::replace(&mut self.handle, new_handle);
Arc::new(Mutex::new(TcpSocketState {
// base: KObjectBase::new(),
handle: old_handle,
local_endpoint: self.local_endpoint,
is_listening: false,
}))
};
drop(sockets);
poll_ifaces();
return Ok((new_socket, Endpoint::Ip(remote_endpoint)));
}
drop(socket);
drop(sockets);
}
}
#[cfg(feature = "e1000")]
async fn accept(&mut self) -> Result<(Arc<Mutex<dyn Socket>>, Endpoint), LxError> {
let endpoint = self.local_endpoint.ok_or(LxError::EINVAL)?;
// let net_sockets = get_net_sockets();
// let mut sockets = net_sockets.lock();
// let socket = sockets.get::<TcpSocket>(self.handle.0);
// if socket.is_active() {
// use crate::net::AcceptFuture;
// AcceptFuture {
// socket: &mut socket,
// }
// .await;
use core::task::Poll;
futures::future::poll_fn(|cx| {
self.with(|s| {
if s.is_active() {
Poll::Ready(())
} else {
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
})
})
.await;
let remote_endpoint = self.with(|s| s.remote_endpoint());
// drop(socket);
let new_socket = {
let rx_buffer = TcpSocketBuffer::new(vec![0; TCP_RECVBUF]);
let tx_buffer = TcpSocketBuffer::new(vec![0; TCP_SENDBUF]);
let mut socket = TcpSocket::new(rx_buffer, tx_buffer);
socket.listen(endpoint).unwrap();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let new_handle = GlobalSocketHandle(sockets.add(socket));
let old_handle = ::core::mem::replace(&mut self.handle, new_handle);
Arc::new(Mutex::new(TcpSocketState {
// base: KObjectBase::new(),
handle: old_handle,
local_endpoint: self.local_endpoint,
is_listening: false,
}))
};
return Ok((new_socket, Endpoint::Ip(remote_endpoint)));
}
/// missing documentation
fn endpoint(&self) -> Option<Endpoint> {
self.local_endpoint.map(Endpoint::Ip).or_else(|| {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
let endpoint = socket.local_endpoint();
if endpoint.port != 0 {
Some(Endpoint::Ip(endpoint))
} else {
None
}
})
}
/// missing documentation
fn remote_endpoint(&self) -> Option<Endpoint> {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.is_open() {
Some(Endpoint::Ip(socket.remote_endpoint()))
} else {
None
}
}
fn ioctl(&self) -> SysResult {
Err(LxError::ENOSYS)
}
fn with<R>(&self, f: impl FnOnce(&mut TcpSocket) -> R) -> R {
let res = {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
f(&mut *socket)
};
res
}
}
// impl_kobject!(TcpSocketState);
#[async_trait]
impl Socket for TcpSocketState {
/// read to buffer
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
self.read(data).await
}
/// write from buffer
fn write(&self, _data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
self.write(_data, _sendto_endpoint)
}
/// connect
async fn connect(&self, _endpoint: Endpoint) -> SysResult {
self.connect(_endpoint).await
}
/// wait for some event on a file descriptor
fn poll(&self) -> (bool, bool, bool) {
self.poll()
}
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
self.bind(endpoint)
}
fn listen(&mut self) -> SysResult {
self.listen()
}
fn shutdown(&self) -> SysResult {
self.shutdown()
}
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
self.accept().await
}
fn endpoint(&self) -> Option<Endpoint> {
self.endpoint()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
self.remote_endpoint()
}
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
Ok(0)
}
fn ioctl(&self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
Ok(0)
}
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
warn!("fnctl is unimplemented for this socket");
// now no fnctl impl but need to pass libctest , so just do a trick
match _cmd {
1 => Ok(1),
3 => Ok(0o4000),
_ => Ok(0),
}
}
}

364
linux-object/src/net/udp.rs Normal file
View File

@ -0,0 +1,364 @@
// udpsocket
#![allow(dead_code)]
// crate
use crate::error::LxError;
use crate::error::LxResult;
use crate::net::from_cstr;
use crate::net::get_ephemeral_port;
use crate::net::get_sockets;
// use crate::net::get_net_device;
use crate::net::poll_ifaces;
use crate::net::AddressFamily;
use crate::net::ArpReq;
use crate::net::Endpoint;
use crate::net::GlobalSocketHandle;
use crate::net::IpAddress;
use crate::net::IpEndpoint;
use crate::net::Ipv4Address;
use crate::net::SockAddr;
use crate::net::SockAddrPlaceholder;
use crate::net::Socket;
use crate::net::SysResult;
use crate::net::UDP_METADATA_BUF;
use crate::net::UDP_RECVBUF;
use crate::net::UDP_SENDBUF;
use spin::Mutex;
// alloc
use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec;
// smoltcp
use smoltcp::socket::UdpPacketMetadata;
use smoltcp::socket::UdpSocket;
use smoltcp::socket::UdpSocketBuffer;
// async
use async_trait::async_trait;
// third part
#[allow(unused_imports)]
use zircon_object::impl_kobject;
#[allow(unused_imports)]
use zircon_object::object::*;
/// missing documentation
#[derive(Debug)]
pub struct UdpSocketState {
/// missing documentation
// base: KObjectBase,
/// missing documentation
handle: GlobalSocketHandle,
/// missing documentation
remote_endpoint: Option<IpEndpoint>, // remember remote endpoint for connect()
}
impl Default for UdpSocketState {
fn default() -> Self {
UdpSocketState::new()
}
}
impl UdpSocketState {
/// missing documentation
pub fn new() -> Self {
// println!(
// "udp new"
// );
info!("udp new");
let rx_buffer = UdpSocketBuffer::new(
vec![UdpPacketMetadata::EMPTY; UDP_METADATA_BUF],
vec![0; UDP_RECVBUF],
);
let tx_buffer = UdpSocketBuffer::new(
vec![UdpPacketMetadata::EMPTY; UDP_METADATA_BUF],
vec![0; UDP_SENDBUF],
);
let socket = UdpSocket::new(rx_buffer, tx_buffer);
let handle = GlobalSocketHandle(get_sockets().lock().add(socket));
UdpSocketState {
// base: KObjectBase::new(),
handle,
remote_endpoint: None,
}
}
fn default() -> Self {
Self::new()
}
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
info!("udp read");
loop {
info!("udp read loop");
poll_ifaces();
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
if socket.can_recv() {
if let Ok((size, remote_endpoint)) = socket.recv_slice(data) {
let endpoint = remote_endpoint;
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
return (Ok(size), Endpoint::Ip(endpoint));
}
} else {
return (
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
);
}
drop(socket);
drop(sockets);
}
}
/// missing documentation
#[cfg(feature = "e1000")]
pub async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
use core::task::Poll;
futures::future::poll_fn(|cx| {
self.with(|s| {
if s.can_recv() {
if let Ok((size, remote_endpoint)) = s.recv_slice(data) {
let endpoint = remote_endpoint;
warn!("udp read => size : {} , enpoint : {} ", size, endpoint);
Poll::Ready((Ok(size), Endpoint::Ip(endpoint)))
} else {
warn!("recv faill message");
Poll::Ready((
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
))
}
} else {
warn!("udp can not recv ,because rx buffer is null");
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
})
})
.await
}
/// missing documentation
pub fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult {
info!("udp write");
let remote_endpoint = {
if let Some(Endpoint::Ip(ref endpoint)) = sendto_endpoint {
endpoint
} else if let Some(ref endpoint) = self.remote_endpoint {
endpoint
} else {
return Err(LxError::ENOTCONN);
}
};
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
if socket.endpoint().port == 0 {
let temp_port = get_ephemeral_port();
socket
.bind(IpEndpoint::new(IpAddress::Unspecified, temp_port))
.unwrap();
}
if socket.can_send() {
match socket.send_slice(data, *remote_endpoint) {
Ok(()) => {
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
Ok(data.len())
}
Err(_) => Err(LxError::ENOBUFS),
}
} else {
Err(LxError::ENOBUFS)
}
}
/// missing documentation
pub fn poll(&self) -> (bool, bool, bool) {
info!("udp poll");
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<UdpSocket>(self.handle.0);
let (mut input, mut output, err) = (false, false, false);
if socket.can_recv() {
input = true;
}
if socket.can_send() {
output = true;
}
(input, output, err)
}
async fn connect(&mut self, endpoint: Endpoint) -> SysResult {
#[allow(irrefutable_let_patterns)]
if let Endpoint::Ip(ip) = endpoint {
self.remote_endpoint = Some(ip);
Ok(0)
} else {
Err(LxError::EINVAL)
}
}
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
info!("udp bind");
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
#[allow(irrefutable_let_patterns)]
if let Endpoint::Ip(mut ip) = endpoint {
if ip.port == 0 {
ip.port = get_ephemeral_port();
}
match socket.bind(ip) {
Ok(()) => Ok(0),
Err(_) => Err(LxError::EINVAL),
}
} else {
Err(LxError::EINVAL)
}
}
fn ioctl(&self, request: usize, arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
info!("udp ioctrl");
match request {
// SIOCGARP
0x8954 => {
// TODO: check addr
#[allow(unsafe_code)]
let req = unsafe { &mut *(arg1 as *mut ArpReq) };
if let AddressFamily::Internet = AddressFamily::from(req.arp_pa.family) {
let name = req.arp_dev.as_ptr();
#[allow(unsafe_code)]
let _ifname = unsafe { from_cstr(name) };
let addr = &req.arp_pa as *const SockAddrPlaceholder as *const SockAddr;
#[allow(unsafe_code)]
let _addr = unsafe {
IpAddress::from(Ipv4Address::from_bytes(
&u32::from_be((*addr).addr_in.sin_addr).to_be_bytes()[..],
))
};
// for iface in get_net_device().iter() {
// if iface.get_ifname() == ifname {
// debug!("get arp matched ifname {}", ifname);
// return match iface.get_arp(addr) {
// Some(mac) => {
// // TODO: update flags
// req.arp_ha.data[0..6].copy_from_slice(mac.as_bytes());
// Ok(0)
// }
// None => Err(LxError::ENOENT),
// };
// }
// }
Err(LxError::ENOENT)
} else {
Err(LxError::EINVAL)
}
}
_ => Ok(0),
}
}
fn endpoint(&self) -> Option<Endpoint> {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<UdpSocket>(self.handle.0);
let endpoint = socket.endpoint();
if endpoint.port != 0 {
Some(Endpoint::Ip(endpoint))
} else {
None
}
}
fn remote_endpoint(&self) -> Option<Endpoint> {
self.remote_endpoint.map(Endpoint::Ip)
}
fn with<R>(&self, f: impl FnOnce(&mut UdpSocket) -> R) -> R {
let res = {
let net_sockets = get_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
f(&mut *socket)
};
res
}
}
// impl_kobject!(UdpSocketState);
/// missing in implementation
#[async_trait]
impl Socket for UdpSocketState {
/// read to buffer
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
self.read(data).await
}
/// write from buffer
fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult {
self.write(data, sendto_endpoint)
}
/// connect
async fn connect(&self, endpoint: Endpoint) -> SysResult {
self.connect(endpoint).await
}
/// wait for some event on a file descriptor
fn poll(&self) -> (bool, bool, bool) {
self.poll()
}
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
self.bind(endpoint)
// Err(LxError::EINVAL)
}
fn listen(&mut self) -> SysResult {
Err(LxError::EINVAL)
}
fn shutdown(&self) -> SysResult {
Err(LxError::EINVAL)
}
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
Err(LxError::EINVAL)
}
fn endpoint(&self) -> Option<Endpoint> {
self.endpoint()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
self.remote_endpoint()
}
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
warn!("setsockopt is unimplemented");
Ok(0)
}
/// manipulate file descriptor
fn ioctl(&self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
warn!("ioctl is unimplemented for this socket");
self.ioctl(request, arg1, arg2, arg3)
}
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
warn!("fnctl is unimplemented for this socket");
Ok(0)
}
}

View File

@ -8,8 +8,10 @@ use alloc::{
};
use core::sync::atomic::AtomicI32;
use crate::net::Socket;
use hashbrown::HashMap;
use rcore_fs::vfs::{FileSystem, INode};
use smoltcp::socket::SocketHandle;
use spin::{Mutex, MutexGuard};
use kernel_hal::VirtAddr;
@ -165,6 +167,8 @@ struct LinuxProcessInner {
children: HashMap<KoID, Arc<Process>>,
/// Signal actions
signal_actions: SignalActions,
/// Sockets
sockets: HashMap<SocketHandle, Arc<Mutex<dyn Socket>>>,
}
#[derive(Clone)]
@ -326,6 +330,43 @@ impl LinuxProcess {
inner.files.remove(&fd).map(|_| ()).ok_or(LxError::EBADF)
}
/// Add a socket to the socket set at given `SocketHandle`.
pub fn add_socket(&self, socket: Arc<Mutex<dyn Socket>>) -> LxResult<SocketHandle> {
let inner = self.inner.lock();
let fd = inner.get_free_hd();
self.insert_socket(inner, fd, socket)
// unimplemented!()
}
/// insert a file and fd into the file descriptor table
fn insert_socket(
&self,
mut inner: MutexGuard<LinuxProcessInner>,
fd: SocketHandle,
socket: Arc<Mutex<dyn Socket>>,
) -> LxResult<SocketHandle> {
if inner.sockets.len() < inner.file_limit.cur as usize {
inner.sockets.insert(fd, socket);
Ok(fd)
} else {
Err(LxError::EMFILE)
}
}
/// Get the `Socket` with given `fd`.
pub fn get_socket(&self, fd: SocketHandle) -> LxResult<Arc<Mutex<dyn Socket>>> {
// unimplemented!()
let inner = self.inner.lock();
let socket = inner.sockets.get(&fd).cloned().ok_or(LxError::EBADF);
socket
}
/// Close file descriptor `fd`.
pub fn close_socket(&self, fd: SocketHandle) -> LxResult {
let mut inner = self.inner.lock();
inner.sockets.remove(&fd).map(|_| ()).ok_or(LxError::EBADF)
}
/// Get root INode of the process.
pub fn root_inode(&self) -> &Arc<dyn INode> {
&self.root_inode
@ -464,4 +505,11 @@ impl LinuxProcessInner {
.find(|fd| !self.files.contains_key(fd))
.unwrap()
}
fn get_free_hd(&self) -> SocketHandle {
(10000usize..)
.map(|i| i.into())
.find(|fd| !self.sockets.contains_key(fd))
.unwrap()
}
}

View File

@ -44,6 +44,7 @@ mod consts {
mod file;
mod ipc;
mod misc;
mod net;
mod signal;
mod task;
mod time;
@ -157,21 +158,28 @@ impl Syscall<'_> {
Sys::SCHED_GETAFFINITY => self.unimplemented("sched_getaffinity", Ok(0)),
// socket
// Sys::SOCKET => self.sys_socket(a0, a1, a2),
// Sys::CONNECT => self.sys_connect(a0, a1.into(), a2),
// Sys::ACCEPT => self.sys_accept(a0, a1.into(), a2.into()),
Sys::SOCKET => self.sys_socket(a0, a1, a2),
Sys::CONNECT => self.sys_connect(a0, a1.into(), a2).await,
Sys::ACCEPT => self.sys_accept(a0, a1.into(), a2.into()).await,
// Sys::ACCEPT4 => self.sys_accept(a0, a1.into(), a2.into()), // use accept for accept4
// Sys::SENDTO => self.sys_sendto(a0, a1.into(), a2, a3, a4.into(), a5),
// Sys::RECVFROM => self.sys_recvfrom(a0, a1.into(), a2, a3, a4.into(), a5.into()),
// Sys::SENDMSG => self.sys_sendmsg(),
// Sys::RECVMSG => self.sys_recvmsg(a0, a1.into(), a2),
// Sys::SHUTDOWN => self.sys_shutdown(a0, a1),
// Sys::BIND => self.sys_bind(a0, a1.into(), a2),
// Sys::LISTEN => self.sys_listen(a0, a1),
// Sys::GETSOCKNAME => self.sys_getsockname(a0, a1.into(), a2.into()),
// Sys::GETPEERNAME => self.sys_getpeername(a0, a1.into(), a2.into()),
// Sys::SETSOCKOPT => self.sys_setsockopt(a0, a1, a2, a3.into(), a4),
// Sys::GETSOCKOPT => self.sys_getsockopt(a0, a1, a2, a3.into(), a4.into()),
Sys::SENDTO => self.sys_sendto(a0, a1.into(), a2, a3, a4.into(), a5),
Sys::RECVFROM => {
self.sys_recvfrom(a0, a1.into(), a2, a3, a4.into(), a5.into())
.await
}
Sys::SENDMSG => self.unimplemented("sys_sendmsg(),", Ok(0)),
Sys::RECVMSG => self.unimplemented("sys_recvmsg(a0, a1.into(), a2),", Ok(0)),
Sys::SHUTDOWN => self.sys_shutdown(a0, a1),
Sys::BIND => self.sys_bind(a0, a1.into(), a2),
Sys::LISTEN => self.sys_listen(a0, a1),
Sys::GETSOCKNAME => self.sys_getsockname(a0, a1.into(), a2.into()),
Sys::GETPEERNAME => {
self.unimplemented("sys_getpeername(a0, a1.into(), a2.into()),", Ok(0))
}
Sys::SETSOCKOPT => self.sys_setsockopt(a0, a1, a2, a3.into(), a4),
Sys::GETSOCKOPT => {
self.unimplemented("sys_getsockopt(a0, a1, a2, a3.into(), a4.into()),", Ok(0))
}
// process
Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a3.into(), a4),

258
linux-syscall/src/net.rs Normal file
View File

@ -0,0 +1,258 @@
use super::*;
use linux_object::net::sockaddr_to_endpoint;
use linux_object::net::SockAddr;
use linux_object::net::Socket;
use linux_object::net::TcpSocketState;
use linux_object::net::UdpSocketState;
use spin::Mutex;
impl Syscall<'_> {
/// net socket
pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult {
warn!(
"sys_socket: domain: {:?}, socket_type: {:?}, protocol: {}",
domain, socket_type, protocol
);
let proc = self.linux_process();
let socket: Arc<Mutex<dyn Socket>> = match domain {
// musl
// domain local 1
// domain inet 2
// domain inet6 10
2 | 1 => match socket_type {
// musl socket type
// 1 STREAM
// 2 DGRAM
// 3 RAW
// 4 RDM
// 5 SEQPACKET
// 5 SEQPACKET
// 6 DCCP
// 10 SOCK_PACKET
1 => Arc::new(Mutex::new(TcpSocketState::new())),
2 => Arc::new(Mutex::new(UdpSocketState::new())),
3 => match protocol {
1 => Arc::new(Mutex::new(UdpSocketState::new())),
_ => Arc::new(Mutex::new(UdpSocketState::new())),
},
_ => return Err(LxError::EINVAL),
},
_ => return Err(LxError::EAFNOSUPPORT),
};
// socket
let fd = proc.add_socket(socket)?;
Ok(fd.into())
}
/// net sys_connect
pub async fn sys_connect(
&mut self,
fd: usize,
addr: UserInPtr<SockAddr>,
addr_len: usize,
) -> SysResult {
warn!(
"sys_connect: fd: {}, addr: {:?}, addr_len: {}",
fd, addr, addr_len
);
let mut _proc = self.linux_process();
let sa: SockAddr = addr.read()?;
let endpoint = sockaddr_to_endpoint(sa, addr_len)?;
let socket = _proc.get_socket(fd.into())?;
let x = socket.lock();
x.connect(endpoint).await?;
Ok(0)
}
/// net setsockopt
pub fn sys_setsockopt(
&mut self,
sockfd: usize,
level: usize,
optname: usize,
optval: UserInPtr<u8>,
optlen: usize,
) -> SysResult {
warn!(
"sys_setsockopt : sockfd : {:?}, level : {:?}, optname : {:?}, optval : {:?} , optlen : {:?}",
sockfd, level, optname,optval,optlen
);
let proc = self.linux_process();
let data = optval.read_array(optlen)?;
let socket = proc.get_socket(sockfd.into())?;
let len = socket.lock().setsockopt(level, optname, &data)?;
Ok(len)
}
/// net setsockopt
pub fn sys_sendto(
&mut self,
sockfd: usize,
buffer: UserInPtr<u8>,
length: usize,
flags: usize,
dest_addr: UserInPtr<SockAddr>,
addrlen: usize,
) -> SysResult {
warn!(
"sys_sendto : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addrlen : {:?}",
sockfd,buffer,length,flags,dest_addr,addrlen
);
let proc = self.linux_process();
let data = buffer.read_array(length)?;
let endpoint = if dest_addr.is_null() {
None
} else {
let _sa: SockAddr = dest_addr.read()?;
let endpoint = sockaddr_to_endpoint(dest_addr.read()?, addrlen)?;
Some(endpoint)
};
let socket = proc.get_socket(sockfd.into())?;
let len = socket.lock().write(&data, endpoint)?;
Ok(len)
}
/// net setsockopt
pub async fn sys_recvfrom(
&mut self,
sockfd: usize,
mut buffer: UserOutPtr<u8>,
length: usize,
flags: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
info!(
"sys_recvfrom : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addr_len : {:?}",
sockfd, buffer, length,flags,addr,addr_len
);
let proc = self.linux_process();
let mut data = vec![0u8; length];
let socket = proc.get_socket(sockfd.into())?;
let x = socket.lock();
let (result, endpoint) = x.read(&mut data).await;
if result.is_ok() && !addr.is_null() {
let sockaddr_in = SockAddr::from(endpoint);
sockaddr_in.write_to(addr, addr_len)?;
}
buffer.write_array(&data[..length])?;
result
}
/// net bind
pub fn sys_bind(&mut self, fd: usize, addr: UserInPtr<SockAddr>, addr_len: usize) -> SysResult {
info!("sys_bind: fd={:?} addr={:?} len={}", fd, addr, addr_len);
let proc = self.linux_process();
let sa: SockAddr = addr.read()?;
let endpoint = sockaddr_to_endpoint(sa, addr_len)?;
info!("sys_bind: fd={:?} bind to {:?}", fd, endpoint);
let socket = proc.get_socket(fd.into())?;
let mut x = socket.lock();
x.bind(endpoint)
}
/// net listen
pub fn sys_listen(&mut self, fd: usize, backlog: usize) -> SysResult {
info!("sys_listen: fd={:?} backlog={}", fd, backlog);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let mut x = socket.lock();
x.listen()
}
/// net shutdown
pub fn sys_shutdown(&mut self, fd: usize, how: usize) -> SysResult {
info!("sys_shutdown: fd={:?} how={}", fd, how);
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let x = socket.lock();
x.shutdown()
}
/// net accept
pub async fn sys_accept(
&mut self,
fd: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
warn!(
"sys_accept: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let (new_socket, remote_endpoint) = socket.lock().accept().await?;
let new_fd = proc.add_socket(new_socket)?;
if !addr.is_null() {
let sockaddr_in = SockAddr::from(remote_endpoint);
sockaddr_in.write_to(addr, addr_len)?;
}
Ok(new_fd.into())
}
/// net getsocknames
pub fn sys_getsockname(
&mut self,
fd: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
info!(
"sys_getsockname: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
let proc = self.linux_process();
if addr.is_null() {
return Err(LxError::EINVAL);
}
let socket = proc.get_socket(fd.into())?;
let endpoint = socket.lock().endpoint().ok_or(LxError::EINVAL)?;
let sockaddr_in = SockAddr::from(endpoint);
sockaddr_in.write_to(addr, addr_len)?;
Ok(0)
}
/// net getpeername
pub fn sys_getpeername(
&mut self,
fd: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
info!(
"sys_getpeername: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let proc = self.linux_process();
if addr.is_null() {
return Err(LxError::EINVAL);
}
let socket = proc.get_socket(fd.into())?;
let remote_endpoint = socket.lock().remote_endpoint().ok_or(LxError::EINVAL)?;
let sockaddr_in = SockAddr::from(remote_endpoint);
sockaddr_in.write_to(addr, addr_len)?;
Ok(0)
}
}

View File

@ -1 +1 @@
nightly-2021-11-02
nightly-2021-11-02

View File

@ -28,7 +28,6 @@
/libc-test/functional/ipc_sem-static.exe?
/libc-test/functional/popen.exe?
/libc-test/regression/sem_close-unmap-static.exe?
/libc-test/functional/socket-static.exe?
/libc-test/functional/pthread_cond-static.exe?
/libc-test/regression/pthread-robust-detach.exe?
/libc-test/regression/tls_get_new-dtv.exe?
@ -44,7 +43,6 @@
/libc-test/regression/statvfs.exe?
/libc-test/functional/pthread_robust-static.exe?
/libc-test/functional/tls_align_dlopen.exe?
/libc-test/functional/socket.exe?
/libc-test/functional/sem_open.exe?
/libc-test/regression/pthread_create-oom-static.exe?
/libc-test/regression/pthread_create-oom.exe?

View File

@ -16,12 +16,10 @@
/libc-test/src/functional/ipc_shm-static.exe
/libc-test/src/regression/getpwnam_r-crash-static.exe
/libc-test/src/regression/pthread_rwlock-ebusy-static.exe
/libc-test/src/functional/socket.exe
/libc-test/src/regression/malloc-brk-fail.exe
/libc-test/src/functional/vfork-static.exe
/libc-test/src/functional/pthread_cancel-points-static.exe
/libc-test/src/functional/ipc_sem.exe
/libc-test/src/functional/socket-static.exe
/libc-test/src/functional/tls_align_dlopen.exe
/libc-test/src/functional/fcntl-static.exe
/libc-test/src/regression/pthread_create-oom.exe

View File

@ -53,5 +53,5 @@ executor = { git = "https://github.com/rcore-os/executor.git", rev = "04b6b7b" }
# Bare-metal mode on x86_64
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]
rboot = { git = "https://github.com/rcore-os/rboot.git", rev = "e1dbac1", default-features = false }
rboot = { git = "https://github.com/rcore-os/rboot.git", rev = "39d6e24", default-features = false }
# rvm = { git = "https://github.com/rcore-os/RVM", rev = "e91d625", optional = true }