forked from rcore-os/zCore
306 lines
7.3 KiB
Rust
306 lines
7.3 KiB
Rust
//! 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;
|
|
use lock::mutex::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)
|
|
}
|
|
}
|