1use crate::task::{CurrentTask, EventHandler, WaitCanceler, WaitQueue, Waiter};
6use crate::vfs::FileHandle;
7use crate::vfs::buffers::{AncillaryData, InputBuffer, MessageReadInfo, OutputBuffer};
8use crate::vfs::socket::{
9 AcceptQueue, DEFAULT_LISTEN_BACKLOG, Socket, SocketAddress, SocketDomain, SocketHandle,
10 SocketMessageFlags, SocketOps, SocketPeer, SocketProtocol, SocketShutdownFlags, SocketType,
11};
12use starnix_sync::{LockDepGuard, LockDepMutex, VsockSocketInnerLock, allow_subclass};
13use starnix_uapi::auth::Credentials;
14use starnix_uapi::errors::Errno;
15use starnix_uapi::open_flags::OpenFlags;
16use starnix_uapi::vfs::FdEvents;
17use starnix_uapi::{errno, error, ucred};
18
19pub struct VsockSocket {
23 inner: LockDepMutex<VsockSocketInner, VsockSocketInnerLock>,
24}
25
26struct VsockSocketInner {
27 address: Option<SocketAddress>,
29
30 waiters: WaitQueue,
32
33 state: VsockSocketState,
35}
36
37enum VsockSocketState {
38 Disconnected,
40
41 Listening(AcceptQueue),
43
44 Connected { file: FileHandle, peer_addr: SocketAddress },
46
47 Closed,
49}
50
51fn downcast_socket_to_vsock(socket: &Socket) -> &VsockSocket {
52 socket.downcast_socket::<VsockSocket>().unwrap()
57}
58
59impl VsockSocket {
60 pub fn new(_socket_type: SocketType) -> VsockSocket {
61 VsockSocket {
62 inner: VsockSocketInner {
63 address: None,
64 waiters: WaitQueue::default(),
65 state: VsockSocketState::Disconnected,
66 }
67 .into(),
68 }
69 }
70
71 fn lock(&self) -> LockDepGuard<'_, VsockSocketInner> {
73 self.inner.lock()
74 }
75}
76
77impl SocketOps for VsockSocket {
78 fn connect(
81 &self,
82 _socket: &SocketHandle,
83 _current_task: &CurrentTask,
84 _peer: SocketPeer,
85 ) -> Result<(), Errno> {
86 error!(EPROTOTYPE)
87 }
88
89 fn listen(&self, _socket: &Socket, backlog: i32, _credentials: ucred) -> Result<(), Errno> {
90 let mut inner = self.lock();
91 let is_bound = inner.address.is_some();
92 let backlog = if backlog < 0 { DEFAULT_LISTEN_BACKLOG } else { backlog as usize };
93 match &mut inner.state {
94 VsockSocketState::Disconnected if is_bound => {
95 inner.state = VsockSocketState::Listening(AcceptQueue::new(backlog));
96 Ok(())
97 }
98 VsockSocketState::Listening(queue) => {
99 queue.set_backlog(backlog)?;
100 Ok(())
101 }
102 _ => error!(EINVAL),
103 }
104 }
105
106 fn accept(&self, socket: &Socket, _current_task: &CurrentTask) -> Result<SocketHandle, Errno> {
107 match socket.socket_type {
108 SocketType::Stream | SocketType::SeqPacket => {}
109 _ => return error!(EOPNOTSUPP),
110 }
111 let mut inner = self.lock();
112 let queue = match &mut inner.state {
113 VsockSocketState::Listening(queue) => queue,
114 _ => return error!(EINVAL),
115 };
116 let socket = queue.sockets.pop_front().ok_or_else(|| errno!(EAGAIN))?;
117 Ok(socket)
118 }
119
120 fn bind(
121 &self,
122 _socket: &Socket,
123 _current_task: &CurrentTask,
124 socket_address: SocketAddress,
125 ) -> Result<(), Errno> {
126 match socket_address {
127 SocketAddress::Vsock { .. } => {}
128 _ => return error!(EINVAL),
129 }
130 let mut inner = self.lock();
131 if inner.address.is_some() {
132 return error!(EINVAL);
133 }
134 inner.address = Some(socket_address);
135 Ok(())
136 }
137
138 fn read(
139 &self,
140 _socket: &Socket,
141 current_task: &CurrentTask,
142 data: &mut dyn OutputBuffer,
143 _flags: SocketMessageFlags,
144 ) -> Result<MessageReadInfo, Errno> {
145 let (address, file) = {
146 let inner = self.lock();
147 let address = inner.address.clone();
148
149 match &inner.state {
150 VsockSocketState::Connected { file, .. } => (address, file.clone()),
151 _ => return error!(EBADF),
152 }
153 };
154 let bytes_read =
155 current_task.override_creds(Credentials::root(), || file.read(current_task, data))?;
156 Ok(MessageReadInfo {
157 bytes_read,
158 message_length: bytes_read,
159 address,
160 credentials: None,
161 ancillary_data: vec![],
162 })
163 }
164
165 fn write(
166 &self,
167 _socket: &Socket,
168 current_task: &CurrentTask,
169 data: &mut dyn InputBuffer,
170 _dest_address: &mut Option<SocketAddress>,
171 _ancillary_data: &mut Vec<AncillaryData>,
172 ) -> Result<usize, Errno> {
173 let file = {
174 let inner = self.lock();
175 match &inner.state {
176 VsockSocketState::Connected { file, .. } => file.clone(),
177 _ => return error!(EBADF),
178 }
179 };
180 current_task.override_creds(Credentials::root(), || file.write(current_task, data))
181 }
182
183 fn wait_async(
184 &self,
185 _socket: &Socket,
186 current_task: &CurrentTask,
187 waiter: &Waiter,
188 events: FdEvents,
189 handler: EventHandler,
190 ) -> WaitCanceler {
191 let inner = self.lock();
192 match &inner.state {
193 VsockSocketState::Connected { file, .. } => file
194 .wait_async(current_task, waiter, events, handler)
195 .expect("vsock socket should be connected to a file that can be waited on"),
196 _ => inner.waiters.wait_async_fd_events(waiter, events, handler),
197 }
198 }
199
200 fn query_events(
201 &self,
202 _socket: &Socket,
203 current_task: &CurrentTask,
204 ) -> Result<FdEvents, Errno> {
205 self.lock().query_events(current_task)
206 }
207
208 fn shutdown(&self, _socket: &Socket, _how: SocketShutdownFlags) -> Result<(), Errno> {
209 self.lock().state = VsockSocketState::Closed;
210 Ok(())
211 }
212
213 fn close(&self, _current_task: &CurrentTask, socket: &Socket) {
214 self.shutdown(socket, SocketShutdownFlags::READ | SocketShutdownFlags::WRITE).unwrap();
216 }
217
218 fn getsockname(&self, socket: &Socket) -> Result<SocketAddress, Errno> {
219 let inner = self.lock();
220 if let Some(address) = &inner.address {
221 Ok(address.clone())
222 } else {
223 Ok(SocketAddress::default_for_domain(socket.domain))
224 }
225 }
226
227 fn getpeername(&self, _socket: &Socket) -> Result<SocketAddress, Errno> {
228 let inner = self.lock();
229 match &inner.state {
230 VsockSocketState::Connected { peer_addr, .. } => Ok(peer_addr.clone()),
231 _ => {
232 error!(ENOTCONN)
233 }
234 }
235 }
236}
237
238impl VsockSocket {
239 pub fn remote_connection(
240 &self,
241 socket: &Socket,
242 current_task: &CurrentTask,
243 file: FileHandle,
244 ) -> Result<(), Errno> {
245 assert!(file.flags().contains(OpenFlags::NONBLOCK));
248 if socket.socket_type != SocketType::Stream {
249 return error!(ENOTSUP);
250 }
251 if socket.domain != SocketDomain::Vsock {
252 return error!(EINVAL);
253 }
254
255 let mut inner = self.lock();
256 match &mut inner.state {
257 VsockSocketState::Listening(queue) => {
258 if queue.sockets.len() >= queue.backlog {
259 return error!(EAGAIN);
260 }
261 let remote_socket = Socket::new(
262 current_task,
263 SocketDomain::Vsock,
264 SocketType::Stream,
265 SocketProtocol::default(),
266 true,
267 )?;
268 let _token = allow_subclass();
271 downcast_socket_to_vsock(&remote_socket).lock().state =
272 VsockSocketState::Connected {
273 file,
274 peer_addr: SocketAddress::Vsock {
275 port: u32::MAX,
276 cid: starnix_uapi::VMADDR_CID_HOST,
277 },
278 };
279 queue.sockets.push_back(remote_socket);
280 inner.waiters.notify_fd_events(FdEvents::POLLIN);
281 Ok(())
282 }
283 _ => error!(EINVAL),
284 }
285 }
286}
287
288impl VsockSocketInner {
289 fn query_events(&self, current_task: &CurrentTask) -> Result<FdEvents, Errno> {
290 Ok(match &self.state {
291 VsockSocketState::Disconnected => FdEvents::empty(),
292 VsockSocketState::Connected { file, .. } => current_task
293 .override_creds(Credentials::root(), || file.query_events(current_task))?,
294 VsockSocketState::Listening(queue) => {
295 if !queue.sockets.is_empty() {
296 FdEvents::POLLIN
297 } else {
298 FdEvents::empty()
299 }
300 }
301 VsockSocketState::Closed => FdEvents::POLLHUP,
302 })
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309 use crate::fs::fuchsia::create_fuchsia_pipe;
310 use crate::mm::PAGE_SIZE;
311 use crate::task::dynamic_thread_spawner::SpawnRequestBuilder;
312 use crate::testing::spawn_kernel_and_run;
313 use crate::vfs::EpollFileObject;
314 use crate::vfs::buffers::{VecInputBuffer, VecOutputBuffer};
315 use crate::vfs::socket::SocketFile;
316 use futures::executor::block_on;
317 use starnix_uapi::vfs::EpollEvent;
318 use syncio::Zxio;
319
320 #[::fuchsia::test]
321 async fn test_vsock_socket() {
322 spawn_kernel_and_run(async |current_task| {
323 let (fs1, fs2) = fidl::Socket::create_stream();
324 const VSOCK_PORT: u32 = 5555;
325
326 let listen_socket = Socket::new(
327 ¤t_task,
328 SocketDomain::Vsock,
329 SocketType::Stream,
330 SocketProtocol::default(),
331 false,
332 )
333 .expect("Failed to create socket.");
334 let vsock_ns = current_task.running_state().abstract_vsock_namespace.clone();
335 vsock_ns
336 .bind(¤t_task, VSOCK_PORT, &listen_socket)
337 .expect("Failed to bind socket.");
338 listen_socket.listen(¤t_task, 10).expect("Failed to listen.");
339
340 let listen_socket =
341 vsock_ns.lookup(&VSOCK_PORT).expect("Failed to look up listening socket.");
342 let remote =
343 create_fuchsia_pipe(¤t_task, fs2, OpenFlags::RDWR | OpenFlags::NONBLOCK)
344 .unwrap();
345 listen_socket
346 .downcast_socket::<VsockSocket>()
347 .unwrap()
348 .remote_connection(&listen_socket, ¤t_task, remote)
349 .unwrap();
350
351 let server_socket = listen_socket.accept(¤t_task).unwrap();
352
353 let test_bytes_in: [u8; 5] = [0, 1, 2, 3, 4];
354 assert_eq!(fs1.write(&test_bytes_in[..]).unwrap(), test_bytes_in.len());
355 let mut buffer_iterator = VecOutputBuffer::new(*PAGE_SIZE as usize);
356 let read_message_info = server_socket
357 .read(¤t_task, &mut buffer_iterator, SocketMessageFlags::empty())
358 .unwrap();
359 assert_eq!(read_message_info.bytes_read, test_bytes_in.len());
360 assert_eq!(buffer_iterator.data(), test_bytes_in);
361
362 let test_bytes_out: [u8; 10] = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
363 let mut buffer_iterator = VecInputBuffer::new(&test_bytes_out);
364 server_socket
365 .write(¤t_task, &mut buffer_iterator, &mut None, &mut vec![])
366 .unwrap();
367 assert_eq!(buffer_iterator.bytes_read(), test_bytes_out.len());
368
369 let mut read_back_buf = [0u8; 100];
370 assert_eq!(test_bytes_out.len(), fs1.read(&mut read_back_buf).unwrap());
371 assert_eq!(&read_back_buf[..test_bytes_out.len()], &test_bytes_out);
372
373 server_socket.close(¤t_task);
374 listen_socket.close(¤t_task);
375 })
376 .await;
377 }
378
379 #[::fuchsia::test]
380 async fn test_vsock_write_while_read() {
381 spawn_kernel_and_run(async |current_task| {
382 let kernel = current_task.kernel();
383 let (fs1, fs2) = fidl::Socket::create_stream();
384 let socket = Socket::new(
385 ¤t_task,
386 SocketDomain::Vsock,
387 SocketType::Stream,
388 SocketProtocol::default(),
389 false,
390 )
391 .expect("Failed to create socket.");
392 let remote =
393 create_fuchsia_pipe(¤t_task, fs2, OpenFlags::RDWR | OpenFlags::NONBLOCK)
394 .unwrap();
395 downcast_socket_to_vsock(&socket).lock().state = VsockSocketState::Connected {
396 file: remote,
397 peer_addr: SocketAddress::Vsock {
398 port: u32::MAX,
399 cid: starnix_uapi::VMADDR_CID_HOST,
400 },
401 };
402 let socket_file =
403 SocketFile::from_socket(¤t_task, socket, OpenFlags::RDWR, false)
404 .expect("Failed to create socket file.");
405
406 const XFER_SIZE: usize = 42;
407
408 let socket_clone = socket_file.clone();
409 let closure = move |current_task: &CurrentTask| {
410 let bytes_read =
411 socket_clone.read(current_task, &mut VecOutputBuffer::new(XFER_SIZE)).unwrap();
412 assert_eq!(XFER_SIZE, bytes_read);
413 };
414 let (result, req) =
415 SpawnRequestBuilder::new().with_sync_closure(closure).build_with_async_result();
416 kernel.kthreads.spawner().spawn_from_request(req);
417
418 std::thread::sleep(std::time::Duration::from_secs(2));
420
421 socket_file.write(¤t_task, &mut VecInputBuffer::new(&[0; XFER_SIZE])).unwrap();
422
423 let mut buffer = [0u8; 1024];
424 assert_eq!(XFER_SIZE, fs1.read(&mut buffer).unwrap());
425 assert_eq!(XFER_SIZE, fs1.write(&buffer[..XFER_SIZE]).unwrap());
426 block_on(result).unwrap();
427 })
428 .await;
429 }
430
431 #[::fuchsia::test]
432 async fn test_vsock_poll() {
433 spawn_kernel_and_run(async |current_task| {
434 let (client, server) = zx::Socket::create_stream();
435 let pipe = create_fuchsia_pipe(¤t_task, client, OpenFlags::RDWR)
436 .expect("create_fuchsia_pipe");
437 let server_zxio = Zxio::create(server.into_handle()).expect("Zxio::create");
438 let socket_object = Socket::new(
439 ¤t_task,
440 SocketDomain::Vsock,
441 SocketType::Stream,
442 SocketProtocol::default(),
443 false,
444 )
445 .expect("Failed to create socket.");
446 downcast_socket_to_vsock(&socket_object).lock().state = VsockSocketState::Connected {
447 file: pipe,
448 peer_addr: SocketAddress::Vsock {
449 port: u32::MAX,
450 cid: starnix_uapi::VMADDR_CID_HOST,
451 },
452 };
453 let socket = SocketFile::from_socket(
454 ¤t_task,
455 socket_object.clone(),
456 OpenFlags::RDWR,
457 false,
458 )
459 .expect("Failed to create socket file.");
460
461 assert_eq!(
462 socket.query_events(¤t_task),
463 Ok(FdEvents::POLLOUT | FdEvents::POLLWRNORM)
464 );
465
466 let epoll_object = EpollFileObject::new_file(¤t_task);
467 let epoll_file = epoll_object.downcast_file::<EpollFileObject>().unwrap();
468 let event = EpollEvent::new(FdEvents::POLLIN, 0);
469 epoll_file.add(¤t_task, &socket, &epoll_object, event).expect("poll_file.add");
470
471 let fds = epoll_file.wait(¤t_task, 1, zx::MonotonicInstant::ZERO).expect("wait");
472 assert!(fds.is_empty());
473
474 assert_eq!(server_zxio.write(&[0]).expect("write"), 1);
475
476 assert_eq!(
477 socket.query_events(¤t_task),
478 Ok(FdEvents::POLLOUT
479 | FdEvents::POLLWRNORM
480 | FdEvents::POLLIN
481 | FdEvents::POLLRDNORM)
482 );
483 let fds = epoll_file.wait(¤t_task, 1, zx::MonotonicInstant::ZERO).expect("wait");
484 assert_eq!(fds.len(), 1);
485
486 assert_eq!(socket.read(¤t_task, &mut VecOutputBuffer::new(64)).expect("read"), 1);
487
488 assert_eq!(
489 socket.query_events(¤t_task),
490 Ok(FdEvents::POLLOUT | FdEvents::POLLWRNORM)
491 );
492 let fds = epoll_file.wait(¤t_task, 1, zx::MonotonicInstant::ZERO).expect("wait");
493 assert!(fds.is_empty());
494 })
495 .await;
496 }
497}