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, FsNodeFlags,
15 FsNodeInfo, SpliceOutputBuffer, fileops_impl_nonseekable, fileops_impl_noop_sync,
16};
17use starnix_syscalls::{SyscallArg, SyscallResult};
18use starnix_uapi::auth::Credentials;
19use starnix_uapi::error;
20use starnix_uapi::errors::{Errno, errno};
21use starnix_uapi::file_mode::mode;
22use starnix_uapi::open_flags::OpenFlags;
23use starnix_uapi::vfs::FdEvents;
24
25use super::socket_fs;
26
27pub struct SocketFile {
28 pub(super) socket: SocketHandle,
29}
30
31impl SocketFile {
32 pub fn from_socket(
41 current_task: &CurrentTask,
42 socket: SocketHandle,
43 open_flags: OpenFlags,
44 kernel_private: bool,
45 ) -> Result<FileHandle, Errno> {
46 let fs = socket_fs(current_task.kernel());
47 security::file_system_resolve_security(current_task, &fs)?;
48 let mode = mode!(IFSOCK, 0o777);
49 let flags = if kernel_private { FsNodeFlags::IS_PRIVATE } else { FsNodeFlags::empty() };
50 let node = fs.create_node_with_flags(
51 None,
52 Anon::new_for_socket(),
53 FsNodeInfo::new(mode, current_task.current_fscred()),
54 flags,
55 );
56 socket.set_fs_node(&node);
57 security::socket_post_create(current_task, &socket);
58 Ok(FileObject::new_anonymous(current_task, SocketFile::new(socket), node, open_flags))
59 }
60
61 pub fn new_socket(
63 current_task: &CurrentTask,
64 domain: SocketDomain,
65 socket_type: SocketType,
66 open_flags: OpenFlags,
67 protocol: SocketProtocol,
68 kernel_private: bool,
69 ) -> Result<FileHandle, Errno> {
70 {
71 let socket = Socket::new(current_task, domain, socket_type, protocol, kernel_private)?;
72 SocketFile::from_socket(current_task, socket, open_flags, kernel_private)
73 }
74 }
75
76 pub fn get_from_file(file: &FileHandle) -> Result<DowncastedFile<'_, Self>, Errno> {
77 file.downcast_file::<SocketFile>().ok_or_else(|| errno!(ENOTSOCK))
78 }
79
80 pub fn socket(&self) -> &SocketHandle {
81 &self.socket
82 }
83}
84
85impl FileOps for SocketFile {
86 fileops_impl_nonseekable!();
87 fileops_impl_noop_sync!();
88
89 fn read(
90 &self,
91 file: &FileObject,
92 current_task: &CurrentTask,
93 offset: usize,
94 data: &mut dyn OutputBuffer,
95 ) -> Result<usize, Errno> {
96 debug_assert!(offset == 0);
97 if data.available() == 0 {
100 return Ok(0);
101 }
102 let info = self.recvmsg(current_task, file, data, SocketMessageFlags::empty(), None)?;
103 Ok(info.bytes_read)
104 }
105
106 fn splice_read(
107 &self,
108 file: &FileObject,
109 current_task: &CurrentTask,
110 offset: usize,
111 data: &mut SpliceOutputBuffer<'_>,
112 non_blocking: bool,
113 ) -> Result<usize, Errno> {
114 debug_assert!(offset == 0);
115 if data.available() == 0 {
116 return Ok(0);
117 }
118 let flags = if non_blocking
119 && self.socket.domain == SocketDomain::Unix
120 && self.socket.socket_type == SocketType::Stream
121 {
122 SocketMessageFlags::DONTWAIT
123 } else {
124 SocketMessageFlags::empty()
125 };
126 let info = self.recvmsg(current_task, file, data, flags, None)?;
127 Ok(info.bytes_read)
128 }
129
130 fn write(
131 &self,
132 file: &FileObject,
133 current_task: &CurrentTask,
134 offset: usize,
135 data: &mut dyn InputBuffer,
136 ) -> Result<usize, Errno> {
137 debug_assert!(offset == 0);
138 self.sendmsg(current_task, file, data, None, vec![], SocketMessageFlags::empty())
139 }
140
141 fn wait_async(
142 &self,
143 _file: &FileObject,
144 current_task: &CurrentTask,
145 waiter: &Waiter,
146 events: FdEvents,
147 handler: EventHandler,
148 ) -> Option<WaitCanceler> {
149 Some(self.socket.wait_async(current_task, waiter, events, handler))
150 }
151
152 fn query_events(
153 &self,
154 _file: &FileObject,
155 current_task: &CurrentTask,
156 ) -> Result<FdEvents, Errno> {
157 self.socket.query_events(current_task)
158 }
159
160 fn ioctl(
161 &self,
162 file: &FileObject,
163 current_task: &CurrentTask,
164 request: u32,
165 arg: SyscallArg,
166 ) -> Result<SyscallResult, Errno> {
167 self.socket.ioctl(file, current_task, request, arg)
168 }
169
170 fn close(self: Box<Self>, _file: &FileObjectState, current_task: &CurrentTask) {
171 self.socket.close(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())
186 .map(|c| Some(c.0.into_channel().into()))
187 }
188 }
189}
190
191impl SocketFile {
192 pub fn new(socket: SocketHandle) -> Box<Self> {
193 Box::new(SocketFile { socket })
194 }
195
196 pub fn sendmsg(
206 &self,
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 security::check_socket_sendmsg_access(current_task, &self.socket)?;
215 let bytes_read_before = data.bytes_read();
216
217 let mut op = || {
219 let offset_before = data.bytes_read();
220 let sent_bytes = self.socket.write_unchecked(
221 current_task,
222 data,
223 &mut dest_address,
224 &mut ancillary_data,
225 )?;
226 debug_assert!(data.bytes_read() - offset_before == sent_bytes);
227 if data.available() > 0 {
228 return error!(EAGAIN);
229 }
230 Ok(())
231 };
232
233 let result = if flags.contains(SocketMessageFlags::DONTWAIT) {
234 op()
235 } else {
236 let deadline = self.socket.send_timeout().map(zx::MonotonicInstant::after);
237 file.blocking_op(current_task, FdEvents::POLLOUT | FdEvents::POLLHUP, deadline, op)
238 };
239
240 let bytes_written = data.bytes_read() - bytes_read_before;
241 if bytes_written == 0 {
242 result?;
245 }
246 Ok(bytes_written)
247 }
248
249 pub fn recvmsg(
258 &self,
259 current_task: &CurrentTask,
260 file: &FileObject,
261 data: &mut dyn OutputBuffer,
262 flags: SocketMessageFlags,
263 deadline: Option<zx::MonotonicInstant>,
264 ) -> Result<MessageReadInfo, Errno> {
265 security::check_socket_recvmsg_access(current_task, &self.socket)?;
266 let mut read_info = MessageReadInfo::default();
268
269 let mut op = || {
270 let can_wait_all =
271 self.socket.read_and_append_unchecked(current_task, &mut read_info, data, flags)?;
272
273 let should_wait_all = self.socket.socket_type == SocketType::Stream
274 && flags.contains(SocketMessageFlags::WAITALL)
275 && !flags.contains(SocketMessageFlags::PEEK)
276 && can_wait_all
277 && !self.socket.query_events(current_task)?.contains(FdEvents::POLLHUP);
278 if should_wait_all && data.available() > 0 {
279 return error!(EAGAIN);
280 }
281 Ok(())
282 };
283
284 let dont_wait =
285 flags.intersects(SocketMessageFlags::DONTWAIT | SocketMessageFlags::ERRQUEUE);
286 let result = if dont_wait {
287 op()
288 } else {
289 let deadline =
290 deadline.or_else(|| self.socket.receive_timeout().map(zx::MonotonicInstant::after));
291 file.blocking_op(current_task, FdEvents::POLLIN | FdEvents::POLLHUP, deadline, op)
292 };
293
294 if read_info.bytes_read == 0 {
295 result?;
298 }
299 Ok(read_info)
300 }
301}