1use fuchsia_async as fasync;
8use futures::{AsyncReadExt as _, AsyncWriteExt as _, FutureExt as _, future};
9use std::num::NonZeroUsize;
10use thiserror::Error;
11use zx::HandleBased as _;
12
13const SOCKET_BUFFER_SIZE: usize = 2048;
15
16const MAX_LINE_BUFFER_LENGTH: usize = 4096;
19
20#[derive(Debug, PartialEq, Eq, Error, Clone)]
22pub enum LoggerError {
23 #[error("cannot create socket: {:?}", _0)]
24 CreateSocket(zx::Status),
25
26 #[error("cannot duplicate socket: {:?}", _0)]
27 DuplicateSocket(zx::Status),
28
29 #[error("invalid socket: {:?}", _0)]
30 InvalidSocket(zx::Status),
31}
32
33#[derive(Debug, Error)]
35pub enum LogError {
36 #[error("can't get logs: {:?}", _0)]
38 Read(std::io::Error),
39
40 #[error("can't write logs: {:?}", _0)]
42 Write(std::io::Error),
43}
44
45pub fn create_std_combined_log_stream()
48-> Result<(LoggerStream, zx::NullableHandle, zx::NullableHandle), LoggerError> {
49 let (client, log) = zx::Socket::create_stream();
50
51 let stream = LoggerStream::new(client).map_err(LoggerError::InvalidSocket)?;
52 let clone =
53 log.duplicate_handle(zx::Rights::SAME_RIGHTS).map_err(LoggerError::DuplicateSocket)?;
54
55 Ok((stream, log.into_handle(), clone.into_handle()))
56}
57
58pub fn create_log_stream() -> Result<(LoggerStream, zx::NullableHandle), LoggerError> {
61 let (client, log) = zx::Socket::create_stream();
62
63 let stream = LoggerStream::new(client).map_err(LoggerError::InvalidSocket)?;
64
65 Ok((stream, log.into_handle()))
66}
67pub struct LogStreamReader {
69 fut: future::RemoteHandle<Result<Vec<u8>, LogError>>,
70}
71
72impl LogStreamReader {
73 pub fn new(logger: LoggerStream) -> Self {
74 let (logger_handle, logger_fut) = logger.read_to_end().remote_handle();
75 fasync::Task::spawn(logger_handle).detach();
76 Self { fut: logger_fut }
77 }
78
79 pub async fn get_logs(self) -> Result<Vec<u8>, LogError> {
81 self.fut.await
82 }
83}
84
85pub struct LoggerStream {
89 socket: fasync::Socket,
90}
91
92impl Unpin for LoggerStream {}
93
94impl LoggerStream {
95 pub fn new(socket: zx::Socket) -> Result<LoggerStream, zx::Status> {
98 let l = LoggerStream { socket: fasync::Socket::from_socket(socket) };
99 Ok(l)
100 }
101
102 pub async fn read_to_end(mut self) -> Result<Vec<u8>, LogError> {
104 let mut buffer: Vec<u8> = Vec::new();
105 let _bytes_read = self.socket.read_to_end(&mut buffer).await.map_err(LogError::Read)?;
106 Ok(buffer)
107 }
108
109 pub async fn buffer_drain_and_peek(
114 mut self,
115 writer: &mut SocketLogWriter,
116 peek_fn: Option<impl Fn(&[u8])>,
117 ) -> Result<(), LogError> {
118 let mut line_buffer: Vec<u8> = Vec::with_capacity(MAX_LINE_BUFFER_LENGTH);
119 let mut socket_buffer: Vec<u8> = vec![0; SOCKET_BUFFER_SIZE];
120
121 while let Some(bytes_read) = NonZeroUsize::new(
122 self.socket.read(&mut socket_buffer[..]).await.map_err(LogError::Read)?,
123 ) {
124 let bytes_read = bytes_read.get();
125
126 let newline_iter = socket_buffer[..bytes_read]
127 .iter()
128 .enumerate()
129 .filter_map(|(i, &b)| if b == b'\n' { Some(i) } else { None });
130
131 let mut prev_offset = 0;
132 for idx in newline_iter {
133 let line = &socket_buffer[prev_offset..idx + 1];
134 if !line_buffer.is_empty() {
135 writer.write(line_buffer.drain(..).as_slice()).await?;
136 }
137 if let Some(peek) = &peek_fn {
138 peek(line);
139 }
140 writer.write(line).await?;
141 prev_offset = idx + 1;
142 }
143 if prev_offset != bytes_read {
144 line_buffer.extend_from_slice(&socket_buffer[prev_offset..bytes_read]);
145 }
146
147 if line_buffer.len() > MAX_LINE_BUFFER_LENGTH {
148 let bytes = &line_buffer[..MAX_LINE_BUFFER_LENGTH];
149 if let Some(peek) = &peek_fn {
150 peek(bytes);
151 }
152 writer.write(bytes).await?;
153 line_buffer.drain(..MAX_LINE_BUFFER_LENGTH);
154 }
155 }
156
157 if !line_buffer.is_empty() {
158 let bytes = &line_buffer[..];
159 if let Some(peek) = &peek_fn {
160 peek(bytes);
161 }
162 writer.write(bytes).await?;
163 }
164
165 Ok(())
166 }
167
168 pub async fn buffer_and_drain(self, writer: &mut SocketLogWriter) -> Result<(), LogError> {
170 self.buffer_drain_and_peek(writer, None::<fn(&[u8])>).await
171 }
172
173 pub fn take_socket(self) -> fasync::Socket {
175 self.socket
176 }
177}
178
179pub struct SocketLogWriter {
181 logger: fasync::Socket,
182}
183
184impl SocketLogWriter {
185 pub fn new(logger: fasync::Socket) -> Self {
186 Self { logger }
187 }
188
189 pub async fn write_str(&mut self, s: &str) -> Result<(), LogError> {
190 self.write(s.as_bytes()).await
191 }
192
193 pub async fn write(&mut self, bytes: &[u8]) -> Result<(), LogError> {
194 self.logger.write_all(bytes).await.map_err(LogError::Write)
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201 use anyhow::{Context as _, Error, format_err};
202 use assert_matches::assert_matches;
203 use futures::{TryStreamExt as _, try_join};
204 use rand::distr::{Alphanumeric, SampleString as _};
205 use rand::rng;
206 use std::sync::mpsc;
207 use test_case::test_case;
208
209 #[fuchsia_async::run_singlethreaded(test)]
210 async fn log_writer_reader_work() {
211 let (sock1, sock2) = zx::Socket::create_stream();
212 let mut log_writer = SocketLogWriter::new(fasync::Socket::from_socket(sock1));
213
214 let reader = LoggerStream::new(sock2).unwrap();
215 let reader = LogStreamReader::new(reader);
216
217 log_writer.write_str("this is string one.").await.unwrap();
218 log_writer.write_str("this is string two.").await.unwrap();
219 drop(log_writer);
220
221 let actual = reader.get_logs().await.unwrap();
222 let actual = std::str::from_utf8(&actual).unwrap();
223 assert_eq!(actual, "this is string one.this is string two.".to_owned());
224 }
225
226 #[test_case(String::from("Hello World!") ; "consumes_simple_msg")]
227 #[test_case(get_random_string(10000) ; "consumes_large_msg")]
228 #[fasync::run_singlethreaded(test)]
229 async fn logger_stream_read_to_end(msg: String) -> Result<(), Error> {
230 let (stream, tx) = create_logger_stream()?;
231
232 let () = take_and_write_to_socket(tx, &msg)?;
233 let result = stream.read_to_end().await.context("Failed to read from socket")?;
234 let actual = std::str::from_utf8(&result).context("Failed to parse bytes")?.to_owned();
235
236 assert_eq!(actual, msg);
237 Ok(())
238 }
239
240 #[fasync::run_singlethreaded(test)]
241 async fn logger_stream_read_to_end_consumes_concat_msgs() -> Result<(), Error> {
242 let (stream, tx) = create_logger_stream()?;
243 let msgs =
244 vec!["Hello World!".to_owned(), "Hola Mundo!".to_owned(), "你好,世界!".to_owned()];
245
246 for msg in msgs.iter() {
247 let () = write_to_socket(&tx, &msg)?;
248 }
249 std::mem::drop(tx);
250 let result = stream.read_to_end().await.context("Failed to read from socket")?;
251 let actual = std::str::from_utf8(&result).context("Failed to parse bytes")?.to_owned();
252
253 assert_eq!(actual, msgs.join(""));
254 Ok(())
255 }
256
257 #[fasync::run_singlethreaded(test)]
258 async fn buffer_and_drain_reads_each_line_as_a_new_message() -> Result<(), Error> {
259 let (stream, tx) = create_logger_stream()?;
260 let (mut logger, rx) = create_datagram_logger()?;
261 let msg = "Hello World\nHola Mundo!\n你好,世界!";
262
263 let (tx_peeks, rx_peeks) = mpsc::channel();
264
265 let () = take_and_write_to_socket(tx, msg)?;
266 let (actual, ()) = try_join!(read_all_messages(rx), async move {
267 stream
268 .buffer_drain_and_peek(
269 &mut logger,
270 Some(move |line: &[u8]| tx_peeks.send(line.len()).unwrap()),
271 )
272 .await
273 .context("Failed to drain stream")
274 },)?;
275
276 let expected = vec![
277 "Hello World\n".to_string(),
278 "Hola Mundo!\n".to_string(),
279 "你好,世界!".to_string(),
280 ];
281 assert_eq!(actual, expected);
282
283 let lengths = rx_peeks.iter().collect::<Vec<_>>();
284
285 assert_eq!(lengths, expected.iter().map(|v| v.len()).collect::<Vec<_>>());
286
287 Ok(())
288 }
289
290 #[fasync::run_singlethreaded(test)]
291 async fn buffer_and_drain_does_not_buffer_past_maximum_size() -> Result<(), Error> {
292 let msg = get_random_string(MAX_LINE_BUFFER_LENGTH + 10);
293 let (stream, tx) = create_logger_stream()?;
294 let (mut logger, rx) = create_datagram_logger()?;
295
296 let (tx_peeks, rx_peeks) = mpsc::channel();
297
298 let () = take_and_write_to_socket(tx, &msg)?;
299 let (actual, ()) = try_join!(read_all_messages(rx), async move {
300 stream
301 .buffer_drain_and_peek(
302 &mut logger,
303 Some(move |line: &[u8]| {
304 tx_peeks.send(line.len()).unwrap();
305 }),
306 )
307 .await
308 .context("Failed to drain stream")
309 },)?;
310
311 let lengths = rx_peeks.iter().collect::<Vec<_>>();
312
313 assert_eq!(actual.len(), 2);
314 assert_eq!(actual[0], msg[0..MAX_LINE_BUFFER_LENGTH]);
315 assert_eq!(actual[1], msg[MAX_LINE_BUFFER_LENGTH..]);
316
317 assert_eq!(lengths, vec![MAX_LINE_BUFFER_LENGTH, 10]);
318
319 Ok(())
320 }
321
322 #[fasync::run_singlethreaded(test)]
323 async fn buffer_and_drain_dumps_full_buffer_if_no_newline_seen() -> Result<(), Error> {
324 let (stream, tx) = create_logger_stream()?;
325 let (mut logger, rx) = create_datagram_logger()?;
326
327 let ((), ()) = try_join!(
328 async move {
329 let msg = get_random_string(SOCKET_BUFFER_SIZE);
330 let () = write_to_socket(&tx, &msg[..SOCKET_BUFFER_SIZE - 1])?;
333
334 let rx = rx.into_zx_socket();
337 let mut buffer = vec![0u8; SOCKET_BUFFER_SIZE];
338 let maybe_bytes_read = rx.read(&mut buffer);
339 assert_eq!(maybe_bytes_read, Err(zx::Status::SHOULD_WAIT));
340
341 let () = write_to_socket(&tx, &msg[SOCKET_BUFFER_SIZE - 1..SOCKET_BUFFER_SIZE])?;
343
344 let maybe_bytes_read = rx.read(&mut buffer);
346 assert_eq!(maybe_bytes_read, Err(zx::Status::SHOULD_WAIT));
347
348 std::mem::drop(tx);
350
351 let mut rx = fasync::Socket::from_socket(rx);
353 let bytes_read =
354 rx.read(&mut buffer).await.context("Failed to read from socket")?;
355 let msg_written = std::str::from_utf8(&buffer).context("Failed to parse bytes")?;
356
357 assert_eq!(bytes_read, SOCKET_BUFFER_SIZE);
358 assert_eq!(msg_written, msg);
359
360 Ok(())
361 },
362 async move { stream.buffer_and_drain(&mut logger).await.context("Failed to drain stream") },
363 )?;
364
365 Ok(())
366 }
367
368 #[fasync::run_singlethreaded(test)]
369 async fn buffer_and_drain_return_error_if_stream_polls_err() -> Result<(), Error> {
370 let (_tx, rx) = zx::Socket::create_stream();
371 let rx = rx.duplicate_handle(zx::Rights::BASIC).expect("duplicate");
373 let stream = LoggerStream::new(rx).context("Failed to create LoggerStream")?;
374 let (mut logger, _rx) = create_datagram_logger()?;
375
376 let result = stream.buffer_and_drain(&mut logger).await;
377
378 assert_matches!(result, Err(LogError::Read(_)));
379 Ok(())
380 }
381
382 async fn read_all_messages(socket: fasync::Socket) -> Result<Vec<String>, Error> {
383 let mut results = Vec::new();
384 let mut stream = socket.into_datagram_stream();
385 while let Some(bytes) = stream.try_next().await.context("Failed to read socket stream")? {
386 results.push(
387 std::str::from_utf8(&bytes).context("Failed to parse bytes into utf8")?.to_owned(),
388 );
389 }
390
391 Ok(results)
392 }
393
394 fn take_and_write_to_socket(socket: zx::Socket, message: &str) -> Result<(), Error> {
395 write_to_socket(&socket, &message)
396 }
397
398 fn write_to_socket(socket: &zx::Socket, message: &str) -> Result<(), Error> {
399 let bytes_written =
400 socket.write(message.as_bytes()).context("Failed to write to socket")?;
401 match bytes_written == message.len() {
402 true => Ok(()),
403 false => Err(format_err!(
404 "Bytes written to socket doesn't match len of message. Message len = {}. Bytes written = {}",
405 message.len(),
406 bytes_written
407 )),
408 }
409 }
410
411 fn create_datagram_logger() -> Result<(SocketLogWriter, fasync::Socket), Error> {
412 let (tx, rx) = zx::Socket::create_datagram();
413 let logger = SocketLogWriter::new(fasync::Socket::from_socket(tx));
414 let rx = fasync::Socket::from_socket(rx);
415 Ok((logger, rx))
416 }
417
418 fn create_logger_stream() -> Result<(LoggerStream, zx::Socket), Error> {
419 let (tx, rx) = zx::Socket::create_stream();
420 let stream = LoggerStream::new(rx).context("Failed to create LoggerStream")?;
421 Ok((stream, tx))
422 }
423
424 fn get_random_string(size: usize) -> String {
425 Alphanumeric.sample_string(&mut rng(), size)
426 }
427}