mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
纸糊忙等tcp connecting,尚不明确连接可用的机制。
This commit is contained in:
parent
bd5f713617
commit
f438808421
@ -104,33 +104,32 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
|
||||
];
|
||||
mfence();
|
||||
let pid = ProcessManager::current_pcb().pid();
|
||||
let mut show =
|
||||
(syscall_num != SYS_SCHED) && (pid.data() >= 7);
|
||||
// false;
|
||||
let mut show = (syscall_num != SYS_SCHED) && (pid.data() >= 7);
|
||||
// false;
|
||||
|
||||
let to_print = SysCall::try_from(syscall_num);
|
||||
if let Ok(to_print) = to_print {
|
||||
use SysCall::*;
|
||||
match to_print {
|
||||
SYS_ACCEPT | SYS_ACCEPT4 | SYS_BIND | SYS_CONNECT | SYS_SHUTDOWN | SYS_LISTEN => {
|
||||
show &= false;
|
||||
// show &= false;
|
||||
}
|
||||
SYS_RECVFROM | SYS_SENDTO | SYS_SENDMSG | SYS_RECVMSG => {
|
||||
show &= false;
|
||||
// show &= false;
|
||||
}
|
||||
SYS_SOCKET | SYS_GETSOCKNAME | SYS_GETPEERNAME | SYS_SOCKETPAIR | SYS_SETSOCKOPT
|
||||
| SYS_GETSOCKOPT => {
|
||||
show &= false;
|
||||
// show &= false;
|
||||
}
|
||||
SYS_OPEN | SYS_OPENAT | SYS_CREAT | SYS_CLOSE => {
|
||||
show &= false;
|
||||
// show &= false;
|
||||
}
|
||||
SYS_READ | SYS_WRITE | SYS_READV | SYS_WRITEV | SYS_PREAD64 | SYS_PWRITE64
|
||||
| SYS_PREADV | SYS_PWRITEV | SYS_PREADV2 => {
|
||||
show &= false;
|
||||
}
|
||||
_ => {
|
||||
show &= false;
|
||||
// show &= false;
|
||||
}
|
||||
}
|
||||
if show {
|
||||
|
@ -246,8 +246,8 @@ impl IfaceCommon {
|
||||
|
||||
self.bounds.read().iter().for_each(|bound_socket| {
|
||||
// incase our inet socket missed the event, we manually notify it each time we poll
|
||||
bound_socket.on_iface_events();
|
||||
if has_events {
|
||||
bound_socket.on_iface_events();
|
||||
bound_socket
|
||||
.wait_queue()
|
||||
.wakeup(Some(ProcessState::Blocked(true)));
|
||||
|
@ -645,6 +645,7 @@ impl Iface for VirtioInterface {
|
||||
}
|
||||
|
||||
fn poll(&self) {
|
||||
// log::debug!("VirtioInterface: poll");
|
||||
self.iface_common.poll(self.device_inner.force_get_mut())
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub fn net_init() -> Result<(), SystemError> {
|
||||
|
||||
fn dhcp_query() -> Result<(), SystemError> {
|
||||
let binding = NET_DEVICES.write_irqsave();
|
||||
log::debug!("binding: {:?}", *binding);
|
||||
// log::debug!("binding: {:?}", *binding);
|
||||
//由于现在os未实现在用户态为网卡动态分配内存,而lo网卡的id最先分配且ip固定不能被分配
|
||||
//所以特判取用id为1的网卡(也就是virtio_net)
|
||||
let net_face = binding.get(&1).ok_or(SystemError::ENODEV)?.clone();
|
||||
@ -63,7 +63,7 @@ fn dhcp_query() -> Result<(), SystemError> {
|
||||
// let dhcp_handle = SOCKET_SET.lock_irqsave().add(dhcp_socket);
|
||||
let dhcp_handle = sockets().add(dhcp_socket);
|
||||
|
||||
const DHCP_TRY_ROUND: u8 = 10;
|
||||
const DHCP_TRY_ROUND: u8 = 100;
|
||||
for i in 0..DHCP_TRY_ROUND {
|
||||
log::debug!("DHCP try round: {}", i);
|
||||
net_face.poll();
|
||||
@ -137,8 +137,8 @@ fn dhcp_query() -> Result<(), SystemError> {
|
||||
drop(binding);
|
||||
|
||||
let sleep_time = PosixTimeSpec {
|
||||
tv_sec: 5,
|
||||
tv_nsec: 0,
|
||||
tv_sec: 0,
|
||||
tv_nsec: 50,
|
||||
};
|
||||
let _ = nanosleep(sleep_time)?;
|
||||
}
|
||||
@ -147,7 +147,7 @@ fn dhcp_query() -> Result<(), SystemError> {
|
||||
}
|
||||
|
||||
pub fn poll_ifaces() {
|
||||
// log::debug!("poll_ifaces");
|
||||
log::debug!("poll_ifaces");
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn Iface>>> = NET_DEVICES.read_irqsave();
|
||||
if guard.len() == 0 {
|
||||
warn!("poll_ifaces: No net driver found!");
|
||||
|
@ -106,10 +106,8 @@ impl core::convert::TryFrom<u16> for AddressFamily {
|
||||
type Error = system_error::SystemError;
|
||||
fn try_from(x: u16) -> Result<Self, Self::Error> {
|
||||
use num_traits::FromPrimitive;
|
||||
return <Self as FromPrimitive>::from_u16(x).ok_or({
|
||||
log::debug!("AddressFamily::try_from failed: x={}", x);
|
||||
Self::Error::EINVAL
|
||||
});
|
||||
// this will return EINVAL but still works, idk why
|
||||
return <Self as FromPrimitive>::from_u16(x).ok_or(Self::Error::EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,11 +84,11 @@ impl UdpSocket {
|
||||
&self,
|
||||
buf: &mut [u8],
|
||||
) -> Result<(usize, smoltcp::wire::IpEndpoint), SystemError> {
|
||||
poll_ifaces();
|
||||
let received = match self.inner.read().as_ref().expect("Udp Inner is None") {
|
||||
UdpInner::Bound(bound) => bound.try_recv(buf),
|
||||
_ => Err(ENOTCONN),
|
||||
};
|
||||
poll_ifaces();
|
||||
return received;
|
||||
}
|
||||
|
||||
|
@ -207,16 +207,20 @@ impl Connecting {
|
||||
self.inner.with_mut(f)
|
||||
}
|
||||
|
||||
pub fn into_result(self) -> (Inner, Option<SystemError>) {
|
||||
pub fn into_result(self) -> (Inner, Result<(), SystemError>) {
|
||||
use ConnectResult::*;
|
||||
let result = *self.result.read_irqsave();
|
||||
match result {
|
||||
Connecting => (Inner::Connecting(self), Some(EAGAIN_OR_EWOULDBLOCK)),
|
||||
Connected => (Inner::Established(Established { inner: self.inner }), None),
|
||||
Refused => (Inner::Init(Init::new_bound(self.inner)), Some(ECONNREFUSED)),
|
||||
Connecting => (Inner::Connecting(self), Err(EAGAIN_OR_EWOULDBLOCK)),
|
||||
Connected => (Inner::Established(Established { inner: self.inner }), Ok(())),
|
||||
Refused => (Inner::Init(Init::new_bound(self.inner)), Err(ECONNREFUSED)),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn into_established(self) -> Established {
|
||||
Established { inner: self.inner }
|
||||
}
|
||||
|
||||
/// Returns `true` when `conn_result` becomes ready, which indicates that the caller should
|
||||
/// invoke the `into_result()` method as soon as possible.
|
||||
///
|
||||
@ -224,9 +228,9 @@ impl Connecting {
|
||||
/// _exactly_ once. The caller is responsible for not missing this event.
|
||||
#[must_use]
|
||||
pub(super) fn update_io_events(&self) -> bool {
|
||||
if matches!(*self.result.read_irqsave(), ConnectResult::Connecting) {
|
||||
return false;
|
||||
}
|
||||
// if matches!(*self.result.read_irqsave(), ConnectResult::Connecting) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
self.inner
|
||||
.with_mut(|socket: &mut smoltcp::socket::tcp::Socket| {
|
||||
@ -237,11 +241,14 @@ impl Connecting {
|
||||
|
||||
// Connected
|
||||
if socket.can_send() {
|
||||
log::debug!("can send");
|
||||
*result = ConnectResult::Connected;
|
||||
return true;
|
||||
}
|
||||
// Connecting
|
||||
if socket.is_open() {
|
||||
log::debug!("connecting");
|
||||
*result = ConnectResult::Connecting;
|
||||
return false;
|
||||
}
|
||||
// Refused
|
||||
@ -309,7 +316,6 @@ impl Listening {
|
||||
});
|
||||
|
||||
if let Some(position) = position {
|
||||
// log::debug!("Can accept!");
|
||||
self.connect
|
||||
.store(position, core::sync::atomic::Ordering::Relaxed);
|
||||
pollee.fetch_or(
|
||||
@ -317,7 +323,6 @@ impl Listening {
|
||||
core::sync::atomic::Ordering::Relaxed,
|
||||
);
|
||||
} else {
|
||||
// log::debug!("Can't accept!");
|
||||
pollee.fetch_and(
|
||||
!EPollEventType::EPOLLIN.bits() as usize,
|
||||
core::sync::atomic::Ordering::Relaxed,
|
||||
|
@ -4,7 +4,6 @@ use system_error::SystemError::{self, *};
|
||||
|
||||
use crate::libs::rwlock::RwLock;
|
||||
use crate::net::event_poll::EPollEventType;
|
||||
use crate::net::net_core::poll_ifaces;
|
||||
use crate::net::socket::*;
|
||||
use crate::sched::SchedMode;
|
||||
use inet::{InetSocket, UNSPECIFIED_LOCAL_ENDPOINT_V4, UNSPECIFIED_LOCAL_ENDPOINT_V6};
|
||||
@ -29,14 +28,14 @@ pub struct TcpSocket {
|
||||
}
|
||||
|
||||
impl TcpSocket {
|
||||
pub fn new(nonblock: bool, ver: smoltcp::wire::IpVersion) -> Arc<Self> {
|
||||
pub fn new(_nonblock: bool, ver: smoltcp::wire::IpVersion) -> Arc<Self> {
|
||||
Arc::new_cyclic(|me| Self {
|
||||
inner: RwLock::new(Some(Inner::Init(Init::new(ver)))),
|
||||
shutdown: Shutdown::new(),
|
||||
nonblock: AtomicBool::new(nonblock),
|
||||
nonblock: AtomicBool::new(false),
|
||||
wait_queue: WaitQueue::default(),
|
||||
self_ref: me.clone(),
|
||||
pollee: AtomicUsize::new((EP::EPOLLIN.bits() | EP::EPOLLOUT.bits()) as usize),
|
||||
pollee: AtomicUsize::new(0_usize),
|
||||
})
|
||||
}
|
||||
|
||||
@ -100,7 +99,7 @@ impl TcpSocket {
|
||||
}
|
||||
|
||||
pub fn try_accept(&self) -> Result<(Arc<TcpSocket>, smoltcp::wire::IpEndpoint), SystemError> {
|
||||
poll_ifaces();
|
||||
// poll_ifaces();
|
||||
match self.inner.write().as_mut().expect("Tcp Inner is None") {
|
||||
Inner::Listening(listening) => listening.accept().map(|(stream, remote)| {
|
||||
(
|
||||
@ -112,46 +111,48 @@ impl TcpSocket {
|
||||
}
|
||||
}
|
||||
|
||||
// SHOULD refactor
|
||||
pub fn start_connect(
|
||||
&self,
|
||||
remote_endpoint: smoltcp::wire::IpEndpoint,
|
||||
) -> Result<(), SystemError> {
|
||||
let mut writer = self.inner.write();
|
||||
let inner = writer.take().expect("Tcp Inner is None");
|
||||
let (init, err) = match inner {
|
||||
let (init, result) = match inner {
|
||||
Inner::Init(init) => {
|
||||
let conn_result = init.connect(remote_endpoint);
|
||||
match conn_result {
|
||||
Ok(connecting) => (
|
||||
Inner::Connecting(connecting),
|
||||
if self.is_nonblock() {
|
||||
None
|
||||
if !self.is_nonblock() {
|
||||
Ok(())
|
||||
} else {
|
||||
Some(EINPROGRESS)
|
||||
Err(EINPROGRESS)
|
||||
},
|
||||
),
|
||||
Err((init, err)) => (Inner::Init(init), Some(err)),
|
||||
Err((init, err)) => (Inner::Init(init), Err(err)),
|
||||
}
|
||||
}
|
||||
Inner::Connecting(connecting) if self.is_nonblock() => {
|
||||
(Inner::Connecting(connecting), Some(EALREADY))
|
||||
(Inner::Connecting(connecting), Err(EALREADY))
|
||||
}
|
||||
Inner::Connecting(connecting) => (Inner::Connecting(connecting), None),
|
||||
Inner::Listening(inner) => (Inner::Listening(inner), Some(EISCONN)),
|
||||
Inner::Established(inner) => (Inner::Established(inner), Some(EISCONN)),
|
||||
Inner::Connecting(connecting) => (Inner::Connecting(connecting), Ok(())),
|
||||
Inner::Listening(inner) => (Inner::Listening(inner), Err(EISCONN)),
|
||||
Inner::Established(inner) => (Inner::Established(inner), Err(EISCONN)),
|
||||
};
|
||||
writer.replace(init);
|
||||
|
||||
drop(writer);
|
||||
|
||||
poll_ifaces();
|
||||
|
||||
if let Some(err) = err {
|
||||
return Err(err);
|
||||
match result {
|
||||
Ok(()) | Err(EINPROGRESS) => {
|
||||
init.iface().unwrap().poll();
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
return Ok(());
|
||||
|
||||
writer.replace(init);
|
||||
return result;
|
||||
}
|
||||
|
||||
// for irq use
|
||||
pub fn finish_connect(&self) -> Result<(), SystemError> {
|
||||
let mut writer = self.inner.write();
|
||||
let Inner::Connecting(conn) = writer.take().expect("Tcp Inner is None") else {
|
||||
@ -159,22 +160,32 @@ impl TcpSocket {
|
||||
return Err(EINVAL);
|
||||
};
|
||||
|
||||
let (inner, err) = conn.into_result();
|
||||
let (inner, result) = conn.into_result();
|
||||
writer.replace(inner);
|
||||
drop(writer);
|
||||
|
||||
if let Some(err) = err {
|
||||
return Err(err);
|
||||
}
|
||||
return Ok(());
|
||||
result
|
||||
}
|
||||
|
||||
pub fn check_connect(&self) -> Result<(), SystemError> {
|
||||
match self.inner.read().as_ref().expect("Tcp Inner is None") {
|
||||
Inner::Connecting(_) => Err(EAGAIN_OR_EWOULDBLOCK),
|
||||
Inner::Established(_) => Ok(()), // TODO check established
|
||||
_ => Err(EINVAL), // TODO socket error options
|
||||
}
|
||||
self.update_events();
|
||||
let mut write_state = self.inner.write();
|
||||
let inner = write_state.take().expect("Tcp Inner is None");
|
||||
let (replace, result) = match inner {
|
||||
Inner::Connecting(conn) => {
|
||||
conn.into_result()
|
||||
}
|
||||
Inner::Established(es) => {
|
||||
log::warn!("TODO: check new established");
|
||||
(Inner::Established(es), Ok(()))
|
||||
}, // TODO check established
|
||||
_ => {
|
||||
log::warn!("TODO: connecting socket error options");
|
||||
(inner, Err(EINVAL))
|
||||
}, // TODO socket error options
|
||||
};
|
||||
write_state.replace(replace);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn try_recv(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
@ -194,20 +205,23 @@ impl TcpSocket {
|
||||
}
|
||||
|
||||
pub fn try_send(&self, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
match self.inner.read().as_ref().expect("Tcp Inner is None") {
|
||||
// TODO: add nonblock check of connecting socket
|
||||
let sent = match self.inner.read().as_ref().expect("Tcp Inner is None") {
|
||||
Inner::Established(inner) => {
|
||||
let sent = inner.send_slice(buf);
|
||||
poll_ifaces();
|
||||
sent
|
||||
inner.send_slice(buf)
|
||||
}
|
||||
_ => Err(EINVAL),
|
||||
}
|
||||
};
|
||||
self.inner.read().as_ref().unwrap().iface().unwrap().poll();
|
||||
sent
|
||||
}
|
||||
|
||||
fn update_events(&self) -> bool {
|
||||
match self.inner.read().as_ref().expect("Tcp Inner is None") {
|
||||
Inner::Init(_) => false,
|
||||
Inner::Connecting(connecting) => connecting.update_io_events(),
|
||||
Inner::Connecting(connecting) => {
|
||||
connecting.update_io_events()
|
||||
},
|
||||
Inner::Established(established) => {
|
||||
established.update_io_events(&self.pollee);
|
||||
false
|
||||
@ -219,12 +233,16 @@ impl TcpSocket {
|
||||
}
|
||||
}
|
||||
|
||||
// should only call on accept
|
||||
fn is_acceptable(&self) -> bool {
|
||||
// (self.poll() & EP::EPOLLIN.bits() as usize) != 0
|
||||
self.inner.read().as_ref().unwrap().iface().unwrap().poll();
|
||||
fn in_notify(&self) -> bool {
|
||||
self.update_events();
|
||||
// shouldn't pollee but just get the status of the socket
|
||||
EP::from_bits_truncate(self.poll() as u32).contains(EP::EPOLLIN)
|
||||
}
|
||||
|
||||
fn out_notify(&self) -> bool {
|
||||
self.update_events();
|
||||
EP::from_bits_truncate(self.poll() as u32).contains(EP::EPOLLOUT)
|
||||
}
|
||||
}
|
||||
|
||||
impl Socket for TcpSocket {
|
||||
@ -254,10 +272,18 @@ impl Socket for TcpSocket {
|
||||
}
|
||||
|
||||
fn connect(&self, endpoint: Endpoint) -> Result<(), SystemError> {
|
||||
if let Endpoint::Ip(addr) = endpoint {
|
||||
return self.start_connect(addr);
|
||||
let Endpoint::Ip(endpoint) = endpoint else {
|
||||
log::debug!("TcpSocket::connect: invalid endpoint");
|
||||
return Err(EINVAL);
|
||||
};
|
||||
self.start_connect(endpoint)?; // Only Nonblock or error will return error.
|
||||
|
||||
return loop {
|
||||
match self.check_connect() {
|
||||
Err(EAGAIN_OR_EWOULDBLOCK) => {},
|
||||
result => break result,
|
||||
}
|
||||
}
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
||||
fn poll(&self) -> usize {
|
||||
@ -269,15 +295,17 @@ impl Socket for TcpSocket {
|
||||
}
|
||||
|
||||
fn accept(&self) -> Result<(Arc<Inode>, Endpoint), SystemError> {
|
||||
// could block io
|
||||
if self.is_nonblock() {
|
||||
self.try_accept()
|
||||
} else {
|
||||
loop {
|
||||
// log::debug!("TcpSocket::accept: wake up");
|
||||
match self.try_accept() {
|
||||
Err(EAGAIN_OR_EWOULDBLOCK) => {
|
||||
wq_wait_event_interruptible!(self.wait_queue, self.is_acceptable(), {})?;
|
||||
wq_wait_event_interruptible!(
|
||||
self.wait_queue,
|
||||
self.in_notify(),
|
||||
{}
|
||||
)?;
|
||||
}
|
||||
result => break result,
|
||||
}
|
||||
@ -311,26 +339,32 @@ impl Socket for TcpSocket {
|
||||
}
|
||||
|
||||
fn close(&self) -> Result<(), SystemError> {
|
||||
self.inner
|
||||
.read()
|
||||
.as_ref()
|
||||
.map(|inner| match inner {
|
||||
Inner::Connecting(_) => Err(EINPROGRESS),
|
||||
Inner::Established(es) => {
|
||||
es.close();
|
||||
es.release();
|
||||
Ok(())
|
||||
}
|
||||
Inner::Listening(ls) => {
|
||||
ls.close();
|
||||
Ok(())
|
||||
}
|
||||
Inner::Init(init) => {
|
||||
init.close();
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
.unwrap_or(Ok(()))
|
||||
let inner = self.inner
|
||||
.write()
|
||||
.take().unwrap();
|
||||
|
||||
match inner {
|
||||
// complete connecting socket close logic
|
||||
Inner::Connecting(conn) => {
|
||||
let conn = unsafe { conn.into_established() };
|
||||
conn.close();
|
||||
conn.release();
|
||||
Ok(())
|
||||
},
|
||||
Inner::Established(es) => {
|
||||
es.close();
|
||||
es.release();
|
||||
Ok(())
|
||||
}
|
||||
Inner::Listening(ls) => {
|
||||
ls.close();
|
||||
Ok(())
|
||||
}
|
||||
Inner::Init(init) => {
|
||||
init.close();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_option(&self, level: PSOL, name: usize, val: &[u8]) -> Result<(), SystemError> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user