mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
Support nonblocking option
This commit is contained in:
parent
7f6ef5e12d
commit
48f69c25a9
7
Makefile
7
Makefile
@ -36,6 +36,13 @@ else ifeq ($(AUTO_TEST), boot)
|
||||
CARGO_OSDK_ARGS += --init_args="/regression/boot_hello.sh"
|
||||
else ifeq ($(AUTO_TEST), vsock)
|
||||
CARGO_OSDK_ARGS += --init_args="/regression/run_vsock_test.sh"
|
||||
ifeq ($(QEMU_MACHINE), microvm)
|
||||
CARGO_OSDK_ARGS += --qemu.args="-device vhost-vsock-device,guest-cid=3"
|
||||
else ifeq ($(EMULATE_IOMMU), 1)
|
||||
CARGO_OSDK_ARGS += --qemu.args="-device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3,disable-legacy=on,disable-modern=off,iommu_platform=on,ats=on"
|
||||
else
|
||||
CARGO_OSDK_ARGS += --qemu.args="-device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3,disable-legacy=on,disable-modern=off"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(RELEASE_LTO), 1)
|
||||
|
@ -48,7 +48,6 @@ impl VsockSpace {
|
||||
pub fn poll(&self) -> Result<Option<VsockEvent>> {
|
||||
let mut driver = self.driver.lock_irq_disabled();
|
||||
let guest_cid: u32 = driver.guest_cid() as u32;
|
||||
|
||||
// match the socket and store the buffer body (if valid)
|
||||
let result = driver
|
||||
.poll(|event, body| {
|
||||
@ -68,6 +67,7 @@ impl VsockSpace {
|
||||
if !connected.connection_buffer_add(body) {
|
||||
return Err(SocketError::BufferTooShort);
|
||||
}
|
||||
connected.update_io_events();
|
||||
} else {
|
||||
return Ok(None);
|
||||
}
|
||||
@ -104,6 +104,7 @@ impl VsockSpace {
|
||||
let connected = Arc::new(Connected::new(peer.into(), listen.addr()));
|
||||
connected.update_for_event(&event);
|
||||
listen.push_incoming(connected).unwrap();
|
||||
listen.update_io_events();
|
||||
} else {
|
||||
return_errno_with_message!(
|
||||
Errno::EINVAL,
|
||||
@ -117,7 +118,11 @@ impl VsockSpace {
|
||||
.lock_irq_disabled()
|
||||
.get(&event.destination.into())
|
||||
{
|
||||
// debug!("match a connecting socket. Peer{:?}; local{:?}",connecting.peer_addr(),connecting.local_addr());
|
||||
debug!(
|
||||
"match a connecting socket. Peer{:?}; local{:?}",
|
||||
connecting.peer_addr(),
|
||||
connecting.local_addr()
|
||||
);
|
||||
connecting.update_for_event(&event);
|
||||
connecting.add_events(IoEvents::IN);
|
||||
}
|
||||
@ -133,17 +138,7 @@ impl VsockSpace {
|
||||
return_errno_with_message!(Errno::ENOTCONN, "The socket hasn't connected");
|
||||
}
|
||||
}
|
||||
VsockEventType::Received { length } => {
|
||||
if let Some(connected) = self
|
||||
.connected_sockets
|
||||
.lock_irq_disabled()
|
||||
.get(&event.into())
|
||||
{
|
||||
connected.add_events(IoEvents::IN);
|
||||
} else {
|
||||
return_errno_with_message!(Errno::ENOTCONN, "The socket hasn't connected");
|
||||
}
|
||||
}
|
||||
VsockEventType::Received { length } => {}
|
||||
VsockEventType::CreditRequest => {
|
||||
if let Some(connected) = self
|
||||
.connected_sockets
|
||||
|
@ -7,7 +7,7 @@ use aster_virtio::device::socket::connect::{ConnectionInfo, VsockEvent};
|
||||
|
||||
use super::connecting::Connecting;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
events::{IoEvents, Observer},
|
||||
net::socket::{
|
||||
vsock::{addr::VsockSocketAddr, VSOCK_GLOBAL},
|
||||
SendRecvFlags, SockShutdownCmd,
|
||||
@ -52,21 +52,22 @@ impl Connected {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn recv(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let poller = Poller::new();
|
||||
if !self
|
||||
.poll(IoEvents::IN, Some(&poller))
|
||||
.contains(IoEvents::IN)
|
||||
{
|
||||
poller.wait()?;
|
||||
}
|
||||
|
||||
pub fn try_recv(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut connection = self.connection.lock_irq_disabled();
|
||||
let bytes_read = connection.buffer.drain(buf);
|
||||
|
||||
connection.info.done_forwarding(bytes_read);
|
||||
|
||||
Ok(bytes_read)
|
||||
match bytes_read {
|
||||
0 => {
|
||||
if !connection.peer_requested_shutdown {
|
||||
return_errno_with_message!(Errno::EAGAIN, "the receive buffer is empty");
|
||||
} else {
|
||||
return_errno_with_message!(Errno::ECONNRESET, "the connection is reset");
|
||||
}
|
||||
}
|
||||
bytes_read => Ok(bytes_read),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(&self, buf: &[u8], flags: SendRecvFlags) -> Result<usize> {
|
||||
@ -91,9 +92,9 @@ impl Connected {
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, cmd: SockShutdownCmd) -> Result<()> {
|
||||
let connection = self.connection.lock_irq_disabled();
|
||||
// TODO: deal with cmd
|
||||
if self.should_close() {
|
||||
let connection = self.connection.lock_irq_disabled();
|
||||
let vsockspace = VSOCK_GLOBAL.get().unwrap();
|
||||
vsockspace
|
||||
.driver
|
||||
@ -103,8 +104,11 @@ impl Connected {
|
||||
vsockspace
|
||||
.connected_sockets
|
||||
.lock_irq_disabled()
|
||||
.remove(&self.id())
|
||||
.unwrap();
|
||||
.remove(&self.id());
|
||||
vsockspace
|
||||
.used_ports
|
||||
.lock_irq_disabled()
|
||||
.remove(&self.local_addr().port);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -120,7 +124,6 @@ impl Connected {
|
||||
|
||||
pub fn connection_buffer_add(&self, bytes: &[u8]) -> bool {
|
||||
let mut connection = self.connection.lock_irq_disabled();
|
||||
self.add_events(IoEvents::IN);
|
||||
connection.add(bytes)
|
||||
}
|
||||
|
||||
@ -131,8 +134,35 @@ impl Connected {
|
||||
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||
self.pollee.poll(mask, poller)
|
||||
}
|
||||
pub fn add_events(&self, events: IoEvents) {
|
||||
self.pollee.add_events(events)
|
||||
|
||||
pub fn update_io_events(&self) {
|
||||
let connection = self.connection.lock_irq_disabled();
|
||||
// receive
|
||||
if !connection.buffer.is_empty() {
|
||||
self.pollee.add_events(IoEvents::IN);
|
||||
} else {
|
||||
self.pollee.del_events(IoEvents::IN);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_observer(
|
||||
&self,
|
||||
pollee: &Pollee,
|
||||
observer: Weak<dyn Observer<IoEvents>>,
|
||||
mask: IoEvents,
|
||||
) -> Result<()> {
|
||||
pollee.register_observer(observer, mask);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister_observer(
|
||||
&self,
|
||||
pollee: &Pollee,
|
||||
observer: &Weak<dyn Observer<IoEvents>>,
|
||||
) -> Result<Weak<dyn Observer<IoEvents>>> {
|
||||
pollee
|
||||
.unregister_observer(observer)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "fails to unregister observer"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,11 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::cmp::min;
|
||||
|
||||
use aster_virtio::device::socket::connect::{ConnectionInfo, VsockEvent};
|
||||
|
||||
use super::connected::ConnectionID;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
net::socket::{
|
||||
vsock::{addr::VsockSocketAddr, VSOCK_GLOBAL},
|
||||
SendRecvFlags, SockShutdownCmd,
|
||||
},
|
||||
net::socket::vsock::{addr::VsockSocketAddr, VSOCK_GLOBAL},
|
||||
prelude::*,
|
||||
process::signal::{Pollee, Poller},
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
events::{IoEvents, Observer},
|
||||
net::socket::vsock::{
|
||||
addr::{VsockSocketAddr, VMADDR_CID_ANY, VMADDR_PORT_ANY},
|
||||
VSOCK_GLOBAL,
|
||||
@ -74,8 +74,24 @@ impl Init {
|
||||
self.pollee.poll(mask, poller)
|
||||
}
|
||||
|
||||
pub fn add_events(&self, events: IoEvents) {
|
||||
self.pollee.add_events(events)
|
||||
pub fn register_observer(
|
||||
&self,
|
||||
pollee: &Pollee,
|
||||
observer: Weak<dyn Observer<IoEvents>>,
|
||||
mask: IoEvents,
|
||||
) -> Result<()> {
|
||||
pollee.register_observer(observer, mask);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister_observer(
|
||||
&self,
|
||||
pollee: &Pollee,
|
||||
observer: &Weak<dyn Observer<IoEvents>>,
|
||||
) -> Result<Weak<dyn Observer<IoEvents>>> {
|
||||
pollee
|
||||
.unregister_observer(observer)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "fails to unregister observer"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,16 +2,16 @@
|
||||
|
||||
use super::connected::Connected;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
events::{IoEvents, Observer},
|
||||
net::socket::vsock::{addr::VsockSocketAddr, VSOCK_GLOBAL},
|
||||
prelude::*,
|
||||
process::signal::{Pollee, Poller},
|
||||
};
|
||||
pub struct Listen {
|
||||
addr: VsockSocketAddr,
|
||||
pollee: Pollee,
|
||||
backlog: usize,
|
||||
incoming_connection: SpinLock<VecDeque<Arc<Connected>>>,
|
||||
pollee: Pollee,
|
||||
}
|
||||
|
||||
impl Listen {
|
||||
@ -33,19 +33,10 @@ impl Listen {
|
||||
return_errno_with_message!(Errno::ENOMEM, "Queue in listenging socket is full")
|
||||
}
|
||||
incoming_connections.push_back(connect);
|
||||
self.add_events(IoEvents::IN);
|
||||
Ok(())
|
||||
}
|
||||
pub fn accept(&self) -> Result<Arc<Connected>> {
|
||||
// block waiting connection if no existing connection.
|
||||
let poller = Poller::new();
|
||||
if !self
|
||||
.poll(IoEvents::IN, Some(&poller))
|
||||
.contains(IoEvents::IN)
|
||||
{
|
||||
poller.wait()?;
|
||||
}
|
||||
|
||||
pub fn try_accept(&self) -> Result<Arc<Connected>> {
|
||||
let connection = self
|
||||
.incoming_connection
|
||||
.lock_irq_disabled()
|
||||
@ -56,12 +47,36 @@ impl Listen {
|
||||
|
||||
Ok(connection)
|
||||
}
|
||||
|
||||
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||
self.pollee.poll(mask, poller)
|
||||
}
|
||||
pub fn add_events(&self, events: IoEvents) {
|
||||
self.pollee.add_events(events)
|
||||
|
||||
pub fn update_io_events(&self) {
|
||||
let can_accept = !self.incoming_connection.lock_irq_disabled().is_empty();
|
||||
if can_accept {
|
||||
self.pollee.add_events(IoEvents::IN);
|
||||
} else {
|
||||
self.pollee.del_events(IoEvents::IN);
|
||||
}
|
||||
}
|
||||
pub fn register_observer(
|
||||
&self,
|
||||
pollee: &Pollee,
|
||||
observer: Weak<dyn Observer<IoEvents>>,
|
||||
mask: IoEvents,
|
||||
) -> Result<()> {
|
||||
pollee.register_observer(observer, mask);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister_observer(
|
||||
&self,
|
||||
pollee: &Pollee,
|
||||
observer: &Weak<dyn Observer<IoEvents>>,
|
||||
) -> Result<Weak<dyn Observer<IoEvents>>> {
|
||||
pollee
|
||||
.unregister_observer(observer)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "fails to unregister observer"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,31 +1,25 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::AtomicBool;
|
||||
|
||||
use atomic::Ordering;
|
||||
|
||||
use super::{connected::Connected, connecting::Connecting, init::Init, listen::Listen};
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::file_handle::FileLike,
|
||||
fs::{file_handle::FileLike, utils::StatusFlags},
|
||||
net::socket::{
|
||||
vsock::{addr::VsockSocketAddr, VSOCK_GLOBAL},
|
||||
SendRecvFlags, SockShutdownCmd, Socket, SocketAddr,
|
||||
},
|
||||
prelude::*,
|
||||
process::signal::Poller,
|
||||
process::signal::{Pollee, Poller},
|
||||
};
|
||||
|
||||
pub struct VsockStreamSocket(RwLock<Status>);
|
||||
|
||||
impl VsockStreamSocket {
|
||||
pub(super) fn new_from_init(init: Arc<Init>) -> Self {
|
||||
Self(RwLock::new(Status::Init(init)))
|
||||
}
|
||||
|
||||
pub(super) fn new_from_listen(listen: Arc<Listen>) -> Self {
|
||||
Self(RwLock::new(Status::Listen(listen)))
|
||||
}
|
||||
|
||||
pub(super) fn new_from_connected(connected: Arc<Connected>) -> Self {
|
||||
Self(RwLock::new(Status::Connected(connected)))
|
||||
}
|
||||
pub struct VsockStreamSocket {
|
||||
status: RwLock<Status>,
|
||||
is_nonblocking: AtomicBool,
|
||||
pollee: Pollee,
|
||||
}
|
||||
|
||||
pub enum Status {
|
||||
@ -35,9 +29,82 @@ pub enum Status {
|
||||
}
|
||||
|
||||
impl VsockStreamSocket {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(nonblocking: bool) -> Self {
|
||||
let init = Arc::new(Init::new());
|
||||
Self(RwLock::new(Status::Init(init)))
|
||||
Self {
|
||||
status: RwLock::new(Status::Init(init)),
|
||||
is_nonblocking: AtomicBool::new(nonblocking),
|
||||
pollee: Pollee::new(IoEvents::empty()),
|
||||
}
|
||||
}
|
||||
pub(super) fn new_from_connected(connected: Arc<Connected>) -> Self {
|
||||
Self {
|
||||
status: RwLock::new(Status::Connected(connected)),
|
||||
is_nonblocking: AtomicBool::new(false),
|
||||
pollee: Pollee::new(IoEvents::empty()),
|
||||
}
|
||||
}
|
||||
fn is_nonblocking(&self) -> bool {
|
||||
self.is_nonblocking.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn set_nonblocking(&self, nonblocking: bool) {
|
||||
self.is_nonblocking.store(nonblocking, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn try_accept(&self) -> Result<(Arc<dyn FileLike>, SocketAddr)> {
|
||||
let listen = match &*self.status.read() {
|
||||
Status::Listen(listen) => listen.clone(),
|
||||
Status::Init(_) | Status::Connected(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "The socket is not listening");
|
||||
}
|
||||
};
|
||||
|
||||
let connected = listen.try_accept()?;
|
||||
listen.update_io_events();
|
||||
|
||||
let peer_addr = connected.peer_addr();
|
||||
|
||||
VSOCK_GLOBAL
|
||||
.get()
|
||||
.unwrap()
|
||||
.connected_sockets
|
||||
.lock_irq_disabled()
|
||||
.insert(connected.id(), connected.clone());
|
||||
|
||||
VSOCK_GLOBAL
|
||||
.get()
|
||||
.unwrap()
|
||||
.driver
|
||||
.lock_irq_disabled()
|
||||
.response(&connected.get_info())
|
||||
.map_err(|e| Error::with_message(Errno::EAGAIN, "can not send response packet"))?;
|
||||
|
||||
let socket = Arc::new(VsockStreamSocket::new_from_connected(connected));
|
||||
Ok((socket, peer_addr.into()))
|
||||
}
|
||||
|
||||
fn try_recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
||||
let connected = match &*self.status.read() {
|
||||
Status::Connected(connected) => connected.clone(),
|
||||
Status::Init(_) | Status::Listen(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "the socket is not connected");
|
||||
}
|
||||
};
|
||||
|
||||
let read_size = connected.try_recv(buf)?;
|
||||
connected.update_io_events();
|
||||
|
||||
let peer_addr = self.peer_addr()?;
|
||||
// If buffer is now empty and the peer requested shutdown, finish shutting down the
|
||||
// connection.
|
||||
// TODO: properly place the close request
|
||||
if connected.should_close() {
|
||||
if let Err(e) = self.shutdown(SockShutdownCmd::SHUT_RDWR) {
|
||||
debug!("The error is {:?}", e);
|
||||
}
|
||||
}
|
||||
Ok((read_size, peer_addr))
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +123,47 @@ impl FileLike for VsockStreamSocket {
|
||||
}
|
||||
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||
let inner = self.0.read();
|
||||
match &*inner {
|
||||
Status::Init(init) => init.poll(mask, poller),
|
||||
Status::Listen(listen) => listen.poll(mask, poller),
|
||||
Status::Connected(connect) => connect.poll(mask, poller),
|
||||
self.pollee.poll(mask, poller)
|
||||
}
|
||||
|
||||
fn status_flags(&self) -> StatusFlags {
|
||||
if self.is_nonblocking() {
|
||||
StatusFlags::O_NONBLOCK
|
||||
} else {
|
||||
StatusFlags::empty()
|
||||
}
|
||||
}
|
||||
|
||||
fn set_status_flags(&self, new_flags: StatusFlags) -> Result<()> {
|
||||
if new_flags.contains(StatusFlags::O_NONBLOCK) {
|
||||
self.set_nonblocking(true);
|
||||
} else {
|
||||
self.set_nonblocking(false);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn register_observer(
|
||||
&self,
|
||||
observer: Weak<dyn crate::events::Observer<IoEvents>>,
|
||||
mask: IoEvents,
|
||||
) -> Result<()> {
|
||||
match &*self.status.read() {
|
||||
Status::Init(init) => init.register_observer(&self.pollee, observer, mask),
|
||||
Status::Listen(listen) => listen.register_observer(&self.pollee, observer, mask),
|
||||
Status::Connected(connected) => {
|
||||
connected.register_observer(&self.pollee, observer, mask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unregister_observer(
|
||||
&self,
|
||||
observer: &Weak<dyn crate::events::Observer<IoEvents>>,
|
||||
) -> Result<Weak<dyn crate::events::Observer<IoEvents>>> {
|
||||
match &*self.status.read() {
|
||||
Status::Init(init) => init.unregister_observer(&self.pollee, observer),
|
||||
Status::Listen(listen) => listen.unregister_observer(&self.pollee, observer),
|
||||
Status::Connected(connected) => connected.unregister_observer(&self.pollee, observer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,7 +171,7 @@ impl FileLike for VsockStreamSocket {
|
||||
impl Socket for VsockStreamSocket {
|
||||
fn bind(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let addr = VsockSocketAddr::try_from(sockaddr)?;
|
||||
let inner = self.0.read();
|
||||
let inner = self.status.read();
|
||||
match &*inner {
|
||||
Status::Init(init) => init.bind(addr),
|
||||
Status::Listen(_) | Status::Connected(_) => {
|
||||
@ -80,8 +183,10 @@ impl Socket for VsockStreamSocket {
|
||||
}
|
||||
}
|
||||
|
||||
// Since blocking mode is supported, there is no need to store the connecting status.
|
||||
// TODO: Refactor when blocking mode is supported.
|
||||
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let init = match &*self.0.read() {
|
||||
let init = match &*self.status.read() {
|
||||
Status::Init(init) => init.clone(),
|
||||
Status::Listen(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "The socket is listened");
|
||||
@ -131,7 +236,7 @@ impl Socket for VsockStreamSocket {
|
||||
.unwrap();
|
||||
|
||||
let connected = Arc::new(Connected::from_connecting(connecting));
|
||||
*self.0.write() = Status::Connected(connected.clone());
|
||||
*self.status.write() = Status::Connected(connected.clone());
|
||||
// move connecting socket map to connected sockmap
|
||||
vsockspace
|
||||
.connected_sockets
|
||||
@ -142,7 +247,7 @@ impl Socket for VsockStreamSocket {
|
||||
}
|
||||
|
||||
fn listen(&self, backlog: usize) -> Result<()> {
|
||||
let init = match &*self.0.read() {
|
||||
let init = match &*self.status.read() {
|
||||
Status::Init(init) => init.clone(),
|
||||
Status::Listen(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "The socket is already listened");
|
||||
@ -156,7 +261,7 @@ impl Socket for VsockStreamSocket {
|
||||
"The socket is not bound",
|
||||
))?;
|
||||
let listen = Arc::new(Listen::new(addr, backlog));
|
||||
*self.0.write() = Status::Listen(listen.clone());
|
||||
*self.status.write() = Status::Listen(listen.clone());
|
||||
|
||||
// push listen socket into vsockspace
|
||||
VSOCK_GLOBAL
|
||||
@ -170,76 +275,30 @@ impl Socket for VsockStreamSocket {
|
||||
}
|
||||
|
||||
fn accept(&self) -> Result<(Arc<dyn FileLike>, SocketAddr)> {
|
||||
let listen = match &*self.0.read() {
|
||||
Status::Listen(listen) => listen.clone(),
|
||||
Status::Init(_) | Status::Connected(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "The socket is not listening");
|
||||
}
|
||||
};
|
||||
let connected = listen.accept()?;
|
||||
let peer_addr = connected.peer_addr();
|
||||
|
||||
VSOCK_GLOBAL
|
||||
.get()
|
||||
.unwrap()
|
||||
.connected_sockets
|
||||
.lock_irq_disabled()
|
||||
.insert(connected.id(), connected.clone());
|
||||
|
||||
VSOCK_GLOBAL
|
||||
.get()
|
||||
.unwrap()
|
||||
.driver
|
||||
.lock_irq_disabled()
|
||||
.response(&connected.get_info())
|
||||
.map_err(|e| Error::with_message(Errno::EAGAIN, "can not send response packet"))?;
|
||||
|
||||
let socket = Arc::new(VsockStreamSocket::new_from_connected(connected));
|
||||
Ok((socket, peer_addr.into()))
|
||||
if self.is_nonblocking() {
|
||||
self.try_accept()
|
||||
} else {
|
||||
wait_events(self, IoEvents::IN, || self.try_accept())
|
||||
}
|
||||
}
|
||||
|
||||
fn shutdown(&self, cmd: SockShutdownCmd) -> Result<()> {
|
||||
let inner = self.0.read();
|
||||
if let Status::Connected(connected) = &*inner {
|
||||
let result = connected.shutdown(cmd);
|
||||
if result.is_ok() {
|
||||
let vsockspace = VSOCK_GLOBAL.get().unwrap();
|
||||
vsockspace
|
||||
.used_ports
|
||||
.lock_irq_disabled()
|
||||
.remove(&connected.local_addr().port);
|
||||
vsockspace
|
||||
.connected_sockets
|
||||
.lock_irq_disabled()
|
||||
.remove(&connected.id());
|
||||
match &*self.status.read() {
|
||||
Status::Connected(connected) => connected.shutdown(cmd),
|
||||
Status::Init(_) | Status::Listen(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "The socket is not connected");
|
||||
}
|
||||
result
|
||||
} else {
|
||||
return_errno_with_message!(Errno::EINVAL, "The socket is not connected.");
|
||||
}
|
||||
}
|
||||
|
||||
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
||||
let connected = match &*self.0.read() {
|
||||
Status::Connected(connected) => connected.clone(),
|
||||
Status::Init(_) | Status::Listen(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "the socket is not connected");
|
||||
}
|
||||
};
|
||||
let read_size = connected.recv(buf)?;
|
||||
let peer_addr = self.peer_addr()?;
|
||||
// If buffer is now empty and the peer requested shutdown, finish shutting down the
|
||||
// connection.
|
||||
if connected.should_close() {
|
||||
VSOCK_GLOBAL
|
||||
.get()
|
||||
.unwrap()
|
||||
.driver
|
||||
.lock_irq_disabled()
|
||||
.reset(&connected.get_info())
|
||||
.map_err(|e| Error::with_message(Errno::EAGAIN, "can not send close packet"))?;
|
||||
debug_assert!(flags.is_all_supported());
|
||||
|
||||
if self.is_nonblocking() {
|
||||
self.try_recvfrom(buf, flags)
|
||||
} else {
|
||||
wait_events(self, IoEvents::IN, || self.try_recvfrom(buf, flags))
|
||||
}
|
||||
Ok((read_size, peer_addr))
|
||||
}
|
||||
|
||||
fn sendto(
|
||||
@ -252,7 +311,7 @@ impl Socket for VsockStreamSocket {
|
||||
if remote.is_some() {
|
||||
return_errno_with_message!(Errno::EINVAL, "vsock should not provide remote addr");
|
||||
}
|
||||
let inner = self.0.read();
|
||||
let inner = self.status.read();
|
||||
match &*inner {
|
||||
Status::Connected(connected) => connected.send(buf, flags),
|
||||
Status::Init(_) | Status::Listen(_) => {
|
||||
@ -262,7 +321,7 @@ impl Socket for VsockStreamSocket {
|
||||
}
|
||||
|
||||
fn addr(&self) -> Result<SocketAddr> {
|
||||
let inner = self.0.read();
|
||||
let inner = self.status.read();
|
||||
let addr = match &*inner {
|
||||
Status::Init(init) => init.bound_addr(),
|
||||
Status::Listen(listen) => Some(listen.addr()),
|
||||
@ -276,7 +335,7 @@ impl Socket for VsockStreamSocket {
|
||||
}
|
||||
|
||||
fn peer_addr(&self) -> Result<SocketAddr> {
|
||||
let inner = self.0.read();
|
||||
let inner = self.status.read();
|
||||
if let Status::Connected(connected) = &*inner {
|
||||
Ok(connected.peer_addr().into())
|
||||
} else {
|
||||
@ -285,8 +344,36 @@ impl Socket for VsockStreamSocket {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VsockStreamSocket {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
// TODO: Support timeout
|
||||
fn wait_events<F, R>(socket: &VsockStreamSocket, mask: IoEvents, mut cond: F) -> Result<R>
|
||||
where
|
||||
F: FnMut() -> Result<R>,
|
||||
{
|
||||
let poller = Poller::new();
|
||||
|
||||
loop {
|
||||
match cond() {
|
||||
Err(err) if err.error() == Errno::EAGAIN => (),
|
||||
result => {
|
||||
if let Err(e) = result {
|
||||
debug!("The result of cond() is Error: {:?}", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
let events = match &*socket.status.read() {
|
||||
Status::Init(init) => init.poll(mask, Some(&poller)),
|
||||
Status::Listen(listen) => listen.poll(mask, Some(&poller)),
|
||||
Status::Connected(connected) => connected.poll(mask, Some(&poller)),
|
||||
};
|
||||
|
||||
debug!("events: {:?}", events);
|
||||
if !events.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
poller.wait()?;
|
||||
debug!("pass the poller wait");
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ pub fn sys_socket(domain: i32, type_: i32, protocol: i32) -> Result<SyscallRetur
|
||||
);
|
||||
let nonblocking = sock_flags.contains(SockFlags::SOCK_NONBLOCK);
|
||||
let file_like = match (domain, sock_type, protocol) {
|
||||
(CSocketAddrFamily::AF_UNIX, SockType::SOCK_STREAM, _) => Arc::new(UnixStreamSocket::new(
|
||||
sock_flags.contains(SockFlags::SOCK_NONBLOCK),
|
||||
)) as Arc<dyn FileLike>,
|
||||
(CSocketAddrFamily::AF_UNIX, SockType::SOCK_STREAM, _) => {
|
||||
Arc::new(UnixStreamSocket::new(nonblocking)) as Arc<dyn FileLike>
|
||||
}
|
||||
(
|
||||
CSocketAddrFamily::AF_INET,
|
||||
SockType::SOCK_STREAM,
|
||||
@ -37,7 +37,7 @@ pub fn sys_socket(domain: i32, type_: i32, protocol: i32) -> Result<SyscallRetur
|
||||
Protocol::IPPROTO_IP | Protocol::IPPROTO_UDP,
|
||||
) => DatagramSocket::new(nonblocking) as Arc<dyn FileLike>,
|
||||
(CSocketAddrFamily::AF_VSOCK, SockType::SOCK_STREAM, _) => {
|
||||
Arc::new(VsockStreamSocket::new()) as Arc<dyn FileLike>
|
||||
Arc::new(VsockStreamSocket::new(nonblocking)) as Arc<dyn FileLike>
|
||||
}
|
||||
_ => return_errno_with_message!(Errno::EAFNOSUPPORT, "unsupported domain"),
|
||||
};
|
||||
|
@ -25,7 +25,6 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
use log::debug;
|
||||
|
||||
use super::{
|
||||
error::SocketError,
|
||||
@ -116,7 +115,6 @@ impl VsockEvent {
|
||||
}
|
||||
VirtioVsockOp::Rst | VirtioVsockOp::Shutdown => {
|
||||
header.check_data_is_empty()?;
|
||||
debug!("Disconnected from the peer");
|
||||
let reason = if op == VirtioVsockOp::Rst {
|
||||
DisconnectReason::Reset
|
||||
} else {
|
||||
|
@ -209,7 +209,7 @@ impl SocketDevice {
|
||||
connection_info: &mut ConnectionInfo,
|
||||
buffer_len: usize,
|
||||
) -> Result<(), SocketError> {
|
||||
debug!("connectin info {:?}", connection_info);
|
||||
debug!("connection info {:?}", connection_info);
|
||||
debug!(
|
||||
"peer free from peer: {:?}, buffer len : {:?}",
|
||||
connection_info.peer_free(),
|
||||
|
@ -12,7 +12,7 @@
|
||||
int main()
|
||||
{
|
||||
int sock;
|
||||
char *hello = "Hello from client";
|
||||
char *hello = "Hello from asterinas";
|
||||
char buffer[1024] = { 0 };
|
||||
struct sockaddr_vm serv_addr;
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
int main()
|
||||
{
|
||||
int sock, new_sock;
|
||||
char *hello = "Hello from client";
|
||||
char *hello = "Hello from asterinas";
|
||||
char buffer[1024] = { 0 };
|
||||
struct sockaddr_vm serv_addr, client_addr;
|
||||
int addrlen = sizeof(client_addr);
|
||||
|
Loading…
x
Reference in New Issue
Block a user