1use crate::security;
6use crate::task::{CurrentTask, EventHandler, WaitCanceler, Waiter};
7use crate::vfs::buffers::{AncillaryData, InputBuffer, MessageReadInfo, OutputBuffer};
8use crate::vfs::file_server::serve_file;
9use crate::vfs::socket::{
10 Socket, SocketAddress, SocketDomain, SocketHandle, SocketMessageFlags, SocketProtocol,
11 SocketType,
12};
13use crate::vfs::{
14 Anon, DowncastedFile, FileHandle, FileObject, FileObjectState, FileOps, FsNodeInfo,
15 fileops_impl_nonseekable, fileops_impl_noop_sync,
16};
17use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked, Unlocked};
18use starnix_syscalls::{SyscallArg, SyscallResult};
19use starnix_uapi::auth::Credentials;
20use starnix_uapi::error;
21use starnix_uapi::errors::{Errno, errno};
22use starnix_uapi::file_mode::mode;
23use starnix_uapi::open_flags::OpenFlags;
24use starnix_uapi::vfs::FdEvents;
25use zx::HandleBased;
26
27use super::socket_fs;
28
29pub struct SocketFile {
30 pub(super) socket: SocketHandle,
31}
32
33impl SocketFile {
34 pub fn from_socket<L>(
43 locked: &mut Locked<L>,
44 current_task: &CurrentTask,
45 socket: SocketHandle,
46 open_flags: OpenFlags,
47 kernel_private: bool,
48 ) -> Result<FileHandle, Errno>
49 where
50 L: LockEqualOrBefore<FileOpsCore>,
51 {
52 let fs = socket_fs(locked, current_task.kernel());
53 let mode = mode!(IFSOCK, 0o777);
54 let node = fs.create_node_and_allocate_node_id(
55 Anon::new_for_socket(kernel_private),
56 FsNodeInfo::new(mode, current_task.current_fscred()),
57 );
58 socket.set_fs_node(&node);
59 security::socket_post_create(current_task, &socket);
60 Ok(FileObject::new_anonymous(
61 locked,
62 current_task,
63 SocketFile::new(socket),
64 node,
65 open_flags,
66 ))
67 }
68
69 pub fn new_socket<L>(
71 locked: &mut Locked<L>,
72 current_task: &CurrentTask,
73 domain: SocketDomain,
74 socket_type: SocketType,
75 open_flags: OpenFlags,
76 protocol: SocketProtocol,
77 kernel_private: bool,
78 ) -> Result<FileHandle, Errno>
79 where
80 L: LockEqualOrBefore<FileOpsCore>,
81 {
82 {
83 let socket =
84 Socket::new(locked, current_task, domain, socket_type, protocol, kernel_private)?;
85 SocketFile::from_socket(locked, current_task, socket, open_flags, kernel_private)
86 }
87 }
88
89 pub fn get_from_file(file: &FileHandle) -> Result<DowncastedFile<'_, Self>, Errno> {
90 file.downcast_file::<SocketFile>().ok_or_else(|| errno!(ENOTSOCK))
91 }
92
93 pub fn socket(&self) -> &SocketHandle {
94 &self.socket
95 }
96}
97
98impl FileOps for SocketFile {
99 fileops_impl_nonseekable!();
100 fileops_impl_noop_sync!();
101
102 fn read(
103 &self,
104 locked: &mut Locked<FileOpsCore>,
105 file: &FileObject,
106 current_task: &CurrentTask,
107 offset: usize,
108 data: &mut dyn OutputBuffer,
109 ) -> Result<usize, Errno> {
110 debug_assert!(offset == 0);
111 if data.available() == 0 {
114 return Ok(0);
115 }
116 let info =
117 self.recvmsg(locked, current_task, file, data, SocketMessageFlags::empty(), None)?;
118 Ok(info.bytes_read)
119 }
120
121 fn write(
122 &self,
123 locked: &mut Locked<FileOpsCore>,
124 file: &FileObject,
125 current_task: &CurrentTask,
126 offset: usize,
127 data: &mut dyn InputBuffer,
128 ) -> Result<usize, Errno> {
129 debug_assert!(offset == 0);
130 self.sendmsg(locked, current_task, file, data, None, vec![], SocketMessageFlags::empty())
131 }
132
133 fn wait_async(
134 &self,
135 locked: &mut Locked<FileOpsCore>,
136 _file: &FileObject,
137 current_task: &CurrentTask,
138 waiter: &Waiter,
139 events: FdEvents,
140 handler: EventHandler,
141 ) -> Option<WaitCanceler> {
142 Some(self.socket.wait_async(locked, current_task, waiter, events, handler))
143 }
144
145 fn query_events(
146 &self,
147 locked: &mut Locked<FileOpsCore>,
148 _file: &FileObject,
149 current_task: &CurrentTask,
150 ) -> Result<FdEvents, Errno> {
151 self.socket.query_events(locked, current_task)
152 }
153
154 fn ioctl(
155 &self,
156 locked: &mut Locked<Unlocked>,
157 file: &FileObject,
158 current_task: &CurrentTask,
159 request: u32,
160 arg: SyscallArg,
161 ) -> Result<SyscallResult, Errno> {
162 self.socket.ioctl(locked, file, current_task, request, arg)
163 }
164
165 fn close(
166 self: Box<Self>,
167 locked: &mut Locked<FileOpsCore>,
168 _file: &FileObjectState,
169 current_task: &CurrentTask,
170 ) {
171 self.socket.close(locked, current_task);
172 }
173
174 fn to_handle(
178 &self,
179 file: &FileObject,
180 current_task: &CurrentTask,
181 ) -> Result<Option<zx::NullableHandle>, Errno> {
182 if let Some(handle) = self.socket.to_handle(file, current_task)? {
183 Ok(Some(handle))
184 } else {
185 serve_file(current_task, file, Credentials::root()).map(|c| Some(c.0.into_handle()))
186 }
187 }
188}
189
190impl SocketFile {
191 pub fn new(socket: SocketHandle) -> Box<Self> {
192 Box::new(SocketFile { socket })
193 }
194
195 pub fn sendmsg<L>(
205 &self,
206 locked: &mut Locked<L>,
207 current_task: &CurrentTask,
208 file: &FileObject,
209 data: &mut dyn InputBuffer,
210 mut dest_address: Option<SocketAddress>,
211 mut ancillary_data: Vec<AncillaryData>,
212 flags: SocketMessageFlags,
213 ) -> Result<usize, Errno>
214 where
215 L: LockEqualOrBefore<FileOpsCore>,
216 {
217 let bytes_read_before = data.bytes_read();
218
219 let mut op = |locked: &mut Locked<L>| {
221 let offset_before = data.bytes_read();
222 let sent_bytes = self.socket.write(
223 locked,
224 current_task,
225 data,
226 &mut dest_address,
227 &mut ancillary_data,
228 )?;
229 debug_assert!(data.bytes_read() - offset_before == sent_bytes);
230 if data.available() > 0 {
231 return error!(EAGAIN);
232 }
233 Ok(())
234 };
235
236 let result = if flags.contains(SocketMessageFlags::DONTWAIT) {
237 op(locked)
238 } else {
239 let deadline = self.socket.send_timeout().map(zx::MonotonicInstant::after);
240 file.blocking_op(
241 locked,
242 current_task,
243 FdEvents::POLLOUT | FdEvents::POLLHUP,
244 deadline,
245 op,
246 )
247 };
248
249 let bytes_written = data.bytes_read() - bytes_read_before;
250 if bytes_written == 0 {
251 result?;
254 }
255 Ok(bytes_written)
256 }
257
258 pub fn recvmsg<L>(
267 &self,
268 locked: &mut Locked<L>,
269 current_task: &CurrentTask,
270 file: &FileObject,
271 data: &mut dyn OutputBuffer,
272 flags: SocketMessageFlags,
273 deadline: Option<zx::MonotonicInstant>,
274 ) -> Result<MessageReadInfo, Errno>
275 where
276 L: LockEqualOrBefore<FileOpsCore>,
277 {
278 let mut read_info = MessageReadInfo::default();
280
281 let mut op = |locked: &mut Locked<L>| {
282 let mut info = self.socket.read(locked, current_task, data, flags)?;
283 read_info.append(&mut info);
284 read_info.address = info.address;
285
286 let should_wait_all = self.socket.socket_type == SocketType::Stream
287 && flags.contains(SocketMessageFlags::WAITALL)
288 && !self.socket.query_events(locked, current_task)?.contains(FdEvents::POLLHUP);
289 if should_wait_all && data.available() > 0 {
290 return error!(EAGAIN);
291 }
292 Ok(())
293 };
294
295 let dont_wait =
296 flags.intersects(SocketMessageFlags::DONTWAIT | SocketMessageFlags::ERRQUEUE);
297 let result = if dont_wait {
298 op(locked)
299 } else {
300 let deadline =
301 deadline.or_else(|| self.socket.receive_timeout().map(zx::MonotonicInstant::after));
302 file.blocking_op(
303 locked,
304 current_task,
305 FdEvents::POLLIN | FdEvents::POLLHUP,
306 deadline,
307 op,
308 )
309 };
310
311 if read_info.bytes_read == 0 {
312 result?;
315 }
316 Ok(read_info)
317 }
318}