forked from rcore-os/zCore
Merge pull request #251 from rcore-os/mergeBranch
Initially add socket syscall function
This commit is contained in:
commit
4aedfd4005
|
@ -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 }
|
||||
|
|
|
@ -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!()
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -11,6 +11,7 @@ cfg_if! {
|
|||
|
||||
pub mod boot;
|
||||
pub mod mem;
|
||||
pub mod net;
|
||||
pub mod thread;
|
||||
pub mod timer;
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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"] }
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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],
|
||||
}
|
|
@ -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 Ok(size)");
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
nightly-2021-11-02
|
||||
nightly-2021-11-02
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
Loading…
Reference in New Issue