1#[allow(unused_imports)]
2pub use log::{debug, error, info, log, trace, warn};
3
4use core::future::{poll_fn, Future};
5use core::pin::pin;
6use core::sync::atomic::AtomicBool;
7use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed};
8use core::task::{Context, Poll, Poll::Pending, Poll::Ready};
9
10use portable_atomic::AtomicUsize;
12
13use embassy_futures::join;
14use embassy_futures::select::select;
15#[allow(unused_imports)]
16use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
17use embassy_sync::mutex::{Mutex, MutexGuard};
18use embassy_sync::signal::Signal;
19use embedded_io_async::{BufRead, Read, Write};
20
21use crate::async_channel::ChanIO;
22use sunset::config::MAX_CHANNELS;
23use sunset::error::TrapBug;
24use sunset::event::Event;
25use sunset::ChanData::{Normal, Stderr};
26use sunset::{error, ChanData, ChanHandle, ChanNum, CliServ, Error, Result, Runner};
27
28#[cfg(feature = "multi-thread")]
29pub type SunsetRawMutex = CriticalSectionRawMutex;
30#[cfg(not(feature = "multi-thread"))]
31pub type SunsetRawMutex = NoopRawMutex;
32
33pub type SunsetMutex<T> = Mutex<SunsetRawMutex, T>;
34
35struct Inner<'a, CS: CliServ> {
36 runner: Runner<'a, CS>,
37
38 chan_handles: [Option<ChanHandle>; MAX_CHANNELS],
41}
42
43impl<'a, CS: CliServ> Inner<'a, CS> {
44 fn fetch(&mut self, num: ChanNum) -> Result<(&mut Runner<'a, CS>, &ChanHandle)> {
48 let h = self
49 .chan_handles
50 .get(num.0 as usize)
51 .ok_or(Error::BadChannel { num })?;
52 h.as_ref().map(|ch| (&mut self.runner, ch)).ok_or_else(Error::bug)
53 }
54}
55
56pub struct ProgressHolder<'g, 'a, CS: CliServ> {
59 guard: Option<MutexGuard<'g, SunsetRawMutex, Inner<'a, CS>>>,
60}
61
62impl<'g, 'a, CS: CliServ> ProgressHolder<'g, 'a, CS> {
63 pub fn new() -> Self {
64 Self { guard: None }
65 }
66}
67
68impl<CS: CliServ> Default for ProgressHolder<'_, '_, CS> {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74pub(crate) struct AsyncSunset<'a, CS: CliServ> {
81 inner: SunsetMutex<Inner<'a, CS>>,
82
83 progress_notify: Signal<SunsetRawMutex, ()>,
84 last_progress_idled: AtomicBool,
85
86 moribund: AtomicBool,
91
92 chan_refcounts: [AtomicUsize; MAX_CHANNELS],
96
97 chan_norm_readcounts: [AtomicUsize; MAX_CHANNELS],
101 chan_stderr_readcounts: [AtomicUsize; MAX_CHANNELS],
103}
104
105impl<CS: CliServ> core::fmt::Debug for AsyncSunset<'_, CS> {
106 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 let mut d = f.debug_struct("AsyncSunset");
108 if let Ok(i) = self.inner.try_lock() {
109 d.field("runner", &i.runner);
110 } else {
111 d.field("inner", &"(locked)");
112 }
113 d.finish_non_exhaustive()
114 }
115}
116
117impl<'a, CS: CliServ> AsyncSunset<'a, CS> {
118 pub fn new(runner: Runner<'a, CS>) -> Self {
119 let inner = Inner { runner, chan_handles: Default::default() };
120 let inner = Mutex::new(inner);
121
122 let progress_notify = Signal::new();
123
124 Self {
125 inner,
126 moribund: AtomicBool::new(false),
127 progress_notify,
128 chan_refcounts: Default::default(),
129 chan_norm_readcounts: Default::default(),
130 chan_stderr_readcounts: Default::default(),
131 last_progress_idled: AtomicBool::new(false),
132 }
133 }
134
135 pub async fn run(
137 &self,
138 rsock: &mut impl Read,
139 wsock: &mut impl Write,
140 ) -> Result<()> {
141 let tx_stop = Signal::<SunsetRawMutex, ()>::new();
145 let rx_stop = Signal::<SunsetRawMutex, ()>::new();
146
147 let tx = async {
148 let r = self
149 .output_loop(wsock)
150 .await
151 .inspect(|r| warn!("tx complete {r:?}"));
152 r
153 };
154 let tx = select(tx, tx_stop.wait());
155
156 let mut rxbuf = [0; 1024];
158 let rx = async {
159 loop {
160 let l = match rsock.read(&mut rxbuf).await {
162 Ok(0) => {
163 debug!("net EOF");
164 self.with_runner(|r| r.close_input()).await;
165 self.moribund.store(true, Relaxed);
166 self.wake_progress();
167 break Ok(());
168 }
169 Ok(l) => l,
170 Err(_) => {
171 info!("socket read error");
172 self.with_runner(|r| r.close_input()).await;
173 break Err(Error::ChannelEOF);
174 }
175 };
176 let mut rxbuf = &rxbuf[..l];
177 while !rxbuf.is_empty() {
178 let n = self.input(rxbuf).await?;
179 self.wake_progress();
180 rxbuf = &rxbuf[n..];
181 }
182 }
183 .inspect(|r| warn!("rx complete {r:?}"))
184 };
185
186 let rx = async {
188 let r = select(rx, rx_stop.wait()).await;
189 tx_stop.signal(());
190 r
191 };
192
193 let f = join::join(rx, tx).await;
197 let (_frx, _ftx) = f;
198
199 Ok(())
208 }
209
210 fn wake_progress(&self) {
211 trace!("wake_progress");
212 self.progress_notify.signal(())
213 }
214
215 fn discard_channels(&self, inner: &mut Inner<CS>) -> Result<()> {
216 if let Some((num, dt, _len)) = inner.runner.read_channel_ready() {
217 if self.chan_readcount(num, dt).load(Acquire) == 0 {
218 let ch = inner.chan_handles[num.0 as usize].as_ref().trap()?;
222 inner.runner.discard_read_channel(ch)?;
223 }
224 }
225 Ok(())
226 }
227
228 fn clear_refcounts(&self, inner: &mut Inner<CS>) -> Result<()> {
235 for (ch, count) in
236 inner.chan_handles.iter_mut().zip(self.chan_refcounts.iter())
237 {
238 let count = count.load(Acquire);
239 if count > 0 {
240 debug_assert!(ch.is_some());
241 continue;
242 }
243 if let Some(ch) = ch.take() {
244 inner.runner.channel_done(ch)?;
246 }
247 }
248 Ok(())
249 }
250
251 pub(crate) async fn progress<'g, 'f>(
255 &'g self,
256 ph: &'f mut ProgressHolder<'g, 'a, CS>,
257 ) -> Result<Event<'f, 'a>> {
258 *ph = ProgressHolder::default();
260
261 let need_wait = self.last_progress_idled.load(Relaxed);
273 if need_wait {
274 self.last_progress_idled.store(false, Relaxed);
275 self.progress_notify.wait().await;
276 }
277
278 let inner = ph.guard.insert(self.inner.lock().await);
280
281 self.clear_refcounts(inner)?;
283 self.discard_channels(inner)?;
285
286 if self.moribund.load(Relaxed) {
287 debug!("All data flushed")
289 }
291
292 let ev = inner.runner.progress();
293 if matches!(ev, Ok(Event::None)) {
294 self.last_progress_idled.store(true, Relaxed);
296 }
297 ev
298 }
299
300 pub(crate) async fn with_runner<F, R>(&self, f: F) -> R
301 where
302 F: FnOnce(&mut Runner<CS>) -> R,
303 {
304 let mut inner = self.inner.lock().await;
305 f(&mut inner.runner)
306 }
307
308 fn chan_readcount(&self, num: ChanNum, dt: ChanData) -> &AtomicUsize {
310 let counts = match dt {
311 Normal => &self.chan_norm_readcounts,
312 Stderr => &self.chan_stderr_readcounts,
313 };
314 &counts[num.0 as usize]
315 }
316
317 async fn poll_inner<F, T>(&self, mut f: F) -> T
319 where
320 F: FnMut(&mut Inner<CS>, &mut Context) -> Poll<T>,
321 {
322 poll_fn(|cx| {
323 let i = self.inner.lock();
325 let i = pin!(i);
326 match i.poll(cx) {
327 Poll::Ready(mut inner) => f(&mut inner, cx),
328 Poll::Pending => {
329 Poll::Pending
331 }
332 }
333 })
334 .await
335 }
336
337 pub async fn output_loop(&self, wsock: &mut impl Write) -> Result<()> {
338 poll_fn(|cx| {
339 let i = self.inner.lock();
341 let i = pin!(i);
342 let Ready(mut inner) = i.poll(cx) else {
343 return Pending;
344 };
345
346 loop {
347 let buf = inner.runner.output_buf();
348 if buf.is_empty() {
349 inner.runner.set_output_waker(cx.waker());
351 return Pending;
352 }
353
354 let res = {
355 let w = wsock.write(buf);
356 let w = pin!(w);
357 w.poll(cx)
358 };
359
360 let r = match res {
361 Pending => Pending,
362 Ready(Ok(0)) => {
363 info!("socket EOF");
364 inner.runner.close_output();
365 Ready(error::ChannelEOF.fail())
366 }
367 Ready(Ok(write_len)) => {
368 let buf_len = buf.len();
369 inner.runner.consume_output(write_len);
370 if write_len < buf_len {
371 continue;
375 }
376 Pending
377 }
378 Ready(Err(_e)) => {
379 info!("socket write error");
380 inner.runner.close_output();
381 Ready(error::ChannelEOF.fail())
382 }
383 };
384 if r.is_pending() {
385 inner.runner.set_output_waker(cx.waker());
386 }
387 return r;
388 }
389 })
390 .await
391 }
392
393 pub async fn input(&self, buf: &[u8]) -> Result<usize> {
394 let res = self
395 .poll_inner(|inner, cx| {
396 if inner.runner.is_input_ready() {
397 match inner.runner.input(buf) {
398 Ok(0) => {
399 inner.runner.set_input_waker(cx.waker());
400 Poll::Pending
401 }
402 Ok(n) => Poll::Ready(Ok(n)),
403 Err(e) => Poll::Ready(Err(e)),
404 }
405 } else {
406 inner.runner.set_input_waker(cx.waker());
407 Poll::Pending
408 }
409 })
410 .await;
411 self.wake_progress();
412 res
413 }
414
415 pub(crate) async fn add_channel(
426 &self,
427 handle: ChanHandle,
428 ) -> Result<ChanIO<'_>> {
429 let mut inner = self.inner.lock().await;
430 let num = handle.num();
431 let idx = num.0 as usize;
432 if inner.chan_handles[idx].is_some() {
433 return error::Bug.fail();
434 }
435 inner.chan_handles[idx] = Some(handle);
436
437 debug_assert_eq!(self.chan_refcounts[idx].load(Relaxed), 0);
438 self.chan_refcounts[idx].store(1, Relaxed);
439 Ok(ChanIO::new_normal(num, self))
440 }
441}
442
443#[cfg(feature = "multi-thread")]
445pub(crate) trait MaybeSend: Sync {}
446#[cfg(not(feature = "multi-thread"))]
447pub(crate) trait MaybeSend {}
448
449impl<'a, CS: CliServ> MaybeSend for AsyncSunset<'a, CS> {}
450
451pub(crate) trait ChanCore: MaybeSend {
454 fn inc_chan(&self, num: ChanNum);
455 fn dec_chan(&self, num: ChanNum);
456 fn inc_read_chan(&self, num: ChanNum, dt: ChanData);
457 fn dec_read_chan(&self, num: ChanNum, dt: ChanData);
458
459 fn poll_until_channel_closed(
460 &self,
461 cx: &mut Context,
462 num: ChanNum,
463 ) -> Poll<Result<()>>;
464
465 fn poll_read_channel(
466 &self,
467 cx: &mut Context,
468 num: ChanNum,
469 dt: ChanData,
470 buf: &mut [u8],
471 ) -> Poll<Result<usize>>;
472
473 fn poll_write_channel(
474 &self,
475 cx: &mut Context,
476 num: ChanNum,
477 dt: ChanData,
478 buf: &[u8],
479 ) -> Poll<Result<usize>>;
480
481 fn poll_term_window_change(
483 &self,
484 cx: &mut Context,
485 num: ChanNum,
486 winch: &sunset::packets::WinChange,
487 ) -> Poll<Result<()>>;
488}
489
490impl<'a, CS: CliServ> ChanCore for AsyncSunset<'a, CS> {
491 fn inc_chan(&self, num: ChanNum) {
493 let c = self.chan_refcounts[num.0 as usize].fetch_add(1, Relaxed);
495 debug_assert_ne!(c, 0);
496 debug_assert_ne!(c, usize::MAX);
498 }
499
500 fn dec_chan(&self, num: ChanNum) {
502 let c = self.chan_refcounts[num.0 as usize].fetch_sub(1, AcqRel);
504 debug_assert_ne!(c, 0);
505 if c == 1 {
506 self.wake_progress();
509 }
510 }
511
512 fn inc_read_chan(&self, num: ChanNum, dt: ChanData) {
514 let c = self.chan_readcount(num, dt).fetch_add(1, AcqRel);
515 debug_assert_ne!(c, usize::MAX);
516 }
517
518 fn dec_read_chan(&self, num: ChanNum, dt: ChanData) {
520 let c = self.chan_readcount(num, dt).fetch_sub(1, AcqRel);
521 debug_assert_ne!(c, 0);
522 if c == 1 {
523 self.wake_progress();
526 }
527 }
528
529 fn poll_until_channel_closed(
530 &self,
531 cx: &mut Context,
532 num: ChanNum,
533 ) -> Poll<Result<()>> {
534 let i = self.inner.lock();
536 let i = pin!(i);
537 let Ready(mut inner) = i.poll(cx) else {
538 return Pending;
539 };
540
541 let (runner, h) = inner.fetch(num)?;
542 if runner.is_channel_closed(h) {
543 Poll::Ready(Ok(()))
544 } else {
545 runner.set_channel_read_waker(h, Normal, cx.waker());
547 Poll::Pending
548 }
549 }
550
551 fn poll_read_channel(
553 &self,
554 cx: &mut Context,
555 num: ChanNum,
556 dt: ChanData,
557 buf: &mut [u8],
558 ) -> Poll<Result<usize>> {
559 let i = self.inner.lock();
561 let i = pin!(i);
562 let Ready(mut inner) = i.poll(cx) else {
563 return Pending;
564 };
565
566 let (runner, h) = inner.fetch(num)?;
567 let i = match runner.read_channel(h, dt, buf) {
568 Ok(0) => {
569 trace!("read ch {num:?} dt {dt:?} pending");
571 runner.set_channel_read_waker(h, dt, cx.waker());
572 Poll::Pending
573 }
574 Err(Error::ChannelEOF) => Poll::Ready(Ok(0)),
575 r => {
576 trace!("read ready ch {num:?} dt {dt:?} {r:?}");
577 Poll::Ready(r)
578 }
579 };
580 if matches!(i, Poll::Ready(_)) {
581 self.wake_progress()
582 }
583 i
584 }
585
586 fn poll_write_channel(
587 &self,
588 cx: &mut Context,
589 num: ChanNum,
590 dt: ChanData,
591 buf: &[u8],
592 ) -> Poll<Result<usize>> {
593 let i = self.inner.lock();
595 let i = pin!(i);
596 let Ready(mut inner) = i.poll(cx) else {
597 return Pending;
598 };
599
600 let (runner, h) = inner.fetch(num)?;
601 let l = runner.write_channel(h, dt, buf);
602 if let Ok(0) = l {
603 trace!("write ch {num:?} dt {dt:?} pending");
605 runner.set_channel_read_waker(h, dt, cx.waker());
606 Poll::Pending
607 } else {
608 trace!("write ready ch {num:?} dt {dt:?} {l:?}");
609 self.wake_progress();
610 Poll::Ready(l)
611 }
612 }
613
614 fn poll_term_window_change(
615 &self,
616 cx: &mut Context,
617 num: ChanNum,
618 winch: &sunset::packets::WinChange,
619 ) -> Poll<Result<()>> {
620 let i = self.inner.lock();
622 let i = pin!(i);
623 let Ready(mut inner) = i.poll(cx) else {
624 return Pending;
625 };
626 let (runner, h) = inner.fetch(num)?;
627 Poll::Ready(runner.term_window_change(h, winch))
628 }
629}
630
631pub async fn io_copy<const B: usize, R, W>(r: &mut R, w: &mut W) -> Result<()>
632where
633 R: Read<Error = sunset::Error>,
634 W: Write<Error = sunset::Error>,
635{
636 let mut b = [0u8; B];
637 loop {
638 let n = r.read(&mut b).await?;
639 if n == 0 {
640 return sunset::error::ChannelEOF.fail();
641 }
642 let b = &b[..n];
643 w.write_all(b).await?
644 }
645 #[allow(unreachable_code)]
646 Ok::<_, Error>(())
647}
648
649pub async fn io_copy_nowriteerror<const B: usize, R, W>(
650 r: &mut R,
651 w: &mut W,
652) -> Result<()>
653where
654 R: Read<Error = sunset::Error>,
655 W: Write,
656{
657 let mut b = [0u8; B];
658 loop {
659 let n = r.read(&mut b).await?;
660 if n == 0 {
661 return sunset::error::ChannelEOF.fail();
662 }
663 let b = &b[..n];
664 if let Err(_) = w.write_all(b).await {
665 info!("write error");
666 }
667 }
668 #[allow(unreachable_code)]
669 Ok::<_, Error>(())
670}
671
672pub async fn io_buf_copy<R, W>(r: &mut R, w: &mut W) -> Result<()>
673where
674 R: BufRead<Error = sunset::Error>,
675 W: Write<Error = sunset::Error>,
676{
677 loop {
678 let b = r.fill_buf().await?;
679 if b.is_empty() {
680 return sunset::error::ChannelEOF.fail();
681 }
682 let n = b.len();
683 w.write_all(b).await?;
684 r.consume(n)
685 }
686 #[allow(unreachable_code)]
687 Ok::<_, Error>(())
688}
689
690pub async fn io_buf_copy_noreaderror<R, W>(r: &mut R, w: &mut W) -> Result<()>
691where
692 R: BufRead,
693 W: Write<Error = sunset::Error>,
694{
695 loop {
696 let b = match r.fill_buf().await {
697 Ok(b) => b,
698 Err(_) => {
699 info!("read error");
700 embassy_futures::yield_now().await;
701 continue;
702 }
703 };
704 if b.is_empty() {
705 return sunset::error::ChannelEOF.fail();
706 }
707 let n = b.len();
708 w.write_all(b).await?;
709 r.consume(n)
710 }
711 #[allow(unreachable_code)]
712 Ok::<_, Error>(())
713}