1#[allow(unused_imports)]
2pub use log::{debug, error, info, log, trace, warn};
3
4use core::future::{Future, poll_fn};
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::{Read, Write};
20
21use crate::async_channel::ChanIO;
22use sunset::ChanData::{Normal, Stderr};
23use sunset::config::MAX_CHANNELS;
24use sunset::error::TrapBug;
25use sunset::event::Event;
26use sunset::{ChanData, ChanHandle, ChanNum, CliServ, Error, Result, Runner, error};
27
28#[cfg(feature = "multi-thread")]
36pub type SunsetRawMutex = CriticalSectionRawMutex;
37
38#[cfg(not(feature = "multi-thread"))]
48pub type SunsetRawMutex = NoopRawMutex;
49
50pub type SunsetMutex<T> = Mutex<SunsetRawMutex, T>;
58
59struct Inner<'a, CS: CliServ> {
60 runner: Runner<'a, CS>,
61
62 chan_handles: [Option<ChanHandle>; MAX_CHANNELS],
65}
66
67impl<'a, CS: CliServ> Inner<'a, CS> {
68 fn fetch(&mut self, num: ChanNum) -> Result<(&mut Runner<'a, CS>, &ChanHandle)> {
72 let h = self
73 .chan_handles
74 .get(num.0 as usize)
75 .ok_or(Error::BadChannel { num })?;
76 h.as_ref().map(|ch| (&mut self.runner, ch)).ok_or_else(Error::bug)
77 }
78}
79
80pub struct ProgressHolder<'g, 'a, CS: CliServ> {
83 guard: Option<MutexGuard<'g, SunsetRawMutex, Inner<'a, CS>>>,
84}
85
86impl<'g, 'a, CS: CliServ> ProgressHolder<'g, 'a, CS> {
87 pub fn new() -> Self {
88 Self { guard: None }
89 }
90}
91
92impl<CS: CliServ> Default for ProgressHolder<'_, '_, CS> {
93 fn default() -> Self {
94 Self::new()
95 }
96}
97
98pub(crate) struct AsyncSunset<'a, CS: CliServ> {
105 inner: SunsetMutex<Inner<'a, CS>>,
106
107 progress_notify: Signal<SunsetRawMutex, ()>,
108 last_progress_idled: AtomicBool,
109
110 moribund: AtomicBool,
115
116 chan_refcounts: [AtomicUsize; MAX_CHANNELS],
120
121 chan_norm_readcounts: [AtomicUsize; MAX_CHANNELS],
125 chan_stderr_readcounts: [AtomicUsize; MAX_CHANNELS],
127}
128
129impl<CS: CliServ> core::fmt::Debug for AsyncSunset<'_, CS> {
130 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
131 let mut d = f.debug_struct("AsyncSunset");
132 if let Ok(i) = self.inner.try_lock() {
133 d.field("runner", &i.runner);
134 } else {
135 d.field("inner", &"(locked)");
136 }
137 d.finish_non_exhaustive()
138 }
139}
140
141impl<'a, CS: CliServ> AsyncSunset<'a, CS> {
142 pub fn new(runner: Runner<'a, CS>) -> Self {
143 let inner = Inner { runner, chan_handles: Default::default() };
144 let inner = Mutex::new(inner);
145
146 let progress_notify = Signal::new();
147
148 Self {
149 inner,
150 moribund: AtomicBool::new(false),
151 progress_notify,
152 chan_refcounts: Default::default(),
153 chan_norm_readcounts: Default::default(),
154 chan_stderr_readcounts: Default::default(),
155 last_progress_idled: AtomicBool::new(false),
156 }
157 }
158
159 pub async fn run(
161 &self,
162 rsock: &mut impl Read,
163 wsock: &mut impl Write,
164 ) -> Result<()> {
165 let tx_stop = Signal::<SunsetRawMutex, ()>::new();
169 let rx_stop = Signal::<SunsetRawMutex, ()>::new();
170
171 let tx = async {
172 let r = self
173 .output_loop(wsock)
174 .await
175 .inspect(|r| warn!("tx complete {r:?}"));
176 r
177 };
178 let tx = select(tx, tx_stop.wait());
179
180 let mut rxbuf = [0; 1024];
182 let rx = async {
183 loop {
184 let l = match rsock.read(&mut rxbuf).await {
186 Ok(0) => {
187 debug!("net EOF");
188 self.with_runner(|r| r.close_input()).await;
189 self.moribund.store(true, Relaxed);
190 self.wake_progress();
191 break Ok(());
192 }
193 Ok(l) => l,
194 Err(_) => {
195 info!("socket read error");
196 self.with_runner(|r| r.close_input()).await;
197 break Err(Error::ChannelEOF);
198 }
199 };
200 let mut rxbuf = &rxbuf[..l];
201 while !rxbuf.is_empty() {
202 let n = self.input(rxbuf).await?;
203 self.wake_progress();
204 rxbuf = &rxbuf[n..];
205 }
206 }
207 .inspect(|r| warn!("rx complete {r:?}"))
208 };
209
210 let rx = async {
212 let r = select(rx, rx_stop.wait()).await;
213 tx_stop.signal(());
214 r
215 };
216
217 let f = join::join(rx, tx).await;
221 let (_frx, _ftx) = f;
222
223 Ok(())
232 }
233
234 fn wake_progress(&self) {
235 trace!("wake_progress");
236 self.progress_notify.signal(())
237 }
238
239 fn discard_channels(&self, inner: &mut Inner<CS>) -> Result<()> {
240 if let Some((num, dt, _len)) = inner.runner.read_channel_ready() {
241 if self.chan_readcount(num, dt).load(Acquire) == 0 {
242 let ch = inner.chan_handles[num.0 as usize].as_ref().trap()?;
246 inner.runner.discard_read_channel(ch)?;
247 }
248 }
249 Ok(())
250 }
251
252 fn clear_refcounts(&self, inner: &mut Inner<CS>) -> Result<()> {
259 for (ch, count) in
260 inner.chan_handles.iter_mut().zip(self.chan_refcounts.iter())
261 {
262 let count = count.load(Acquire);
263 if count > 0 {
264 debug_assert!(ch.is_some());
265 continue;
266 }
267 if let Some(ch) = ch.take() {
268 inner.runner.channel_done(ch)?;
270 }
271 }
272 Ok(())
273 }
274
275 pub(crate) async fn progress<'g, 'f>(
279 &'g self,
280 ph: &'f mut ProgressHolder<'g, 'a, CS>,
281 ) -> Result<Event<'f, 'a>> {
282 *ph = ProgressHolder::default();
284
285 let need_wait = self.last_progress_idled.load(Relaxed);
297 if need_wait {
298 self.last_progress_idled.store(false, Relaxed);
299 self.progress_notify.wait().await;
300 }
301
302 let inner = ph.guard.insert(self.inner.lock().await);
304
305 self.clear_refcounts(inner)?;
307 self.discard_channels(inner)?;
309
310 if self.moribund.load(Relaxed) {
311 debug!("All data flushed")
313 }
315
316 let ev = inner.runner.progress();
317 if matches!(ev, Ok(Event::None)) {
318 self.last_progress_idled.store(true, Relaxed);
320 }
321 ev
322 }
323
324 pub(crate) async fn with_runner<F, R>(&self, f: F) -> R
325 where
326 F: FnOnce(&mut Runner<CS>) -> R,
327 {
328 let mut inner = self.inner.lock().await;
329 f(&mut inner.runner)
330 }
331
332 fn chan_readcount(&self, num: ChanNum, dt: ChanData) -> &AtomicUsize {
334 let counts = match dt {
335 Normal => &self.chan_norm_readcounts,
336 Stderr => &self.chan_stderr_readcounts,
337 };
338 &counts[num.0 as usize]
339 }
340
341 async fn poll_inner<F, T>(&self, mut f: F) -> T
343 where
344 F: FnMut(&mut Inner<CS>, &mut Context) -> Poll<T>,
345 {
346 poll_fn(|cx| {
347 let i = self.inner.lock();
349 let i = pin!(i);
350 match i.poll(cx) {
351 Poll::Ready(mut inner) => f(&mut inner, cx),
352 Poll::Pending => {
353 Poll::Pending
355 }
356 }
357 })
358 .await
359 }
360
361 pub async fn output_loop(&self, wsock: &mut impl Write) -> Result<()> {
362 poll_fn(|cx| {
363 let i = self.inner.lock();
365 let i = pin!(i);
366 let Ready(mut inner) = i.poll(cx) else {
367 return Pending;
368 };
369
370 loop {
371 let buf = inner.runner.output_buf();
372 if buf.is_empty() {
373 inner.runner.set_output_waker(cx.waker());
375 return Pending;
376 }
377
378 let res = {
379 let w = wsock.write(buf);
380 let w = pin!(w);
381 w.poll(cx)
382 };
383
384 let r = match res {
385 Pending => {
386 Pending
388 }
389 Ready(Ok(0)) => {
390 info!("socket EOF");
391 inner.runner.close_output();
392 Ready(error::ChannelEOF.fail())
393 }
394 Ready(Ok(write_len)) => {
395 let buf_len = buf.len();
396 inner.runner.consume_output(write_len);
397 if write_len < buf_len {
398 continue;
402 }
403 inner.runner.set_output_waker(cx.waker());
404 if !inner.runner.is_output_pending() {
405 self.wake_progress();
409 }
410 Pending
411 }
412 Ready(Err(_e)) => {
413 info!("socket write error");
414 inner.runner.close_output();
415 Ready(error::ChannelEOF.fail())
416 }
417 };
418 return r;
419 }
420 })
421 .await
422 }
423
424 pub async fn input(&self, buf: &[u8]) -> Result<usize> {
425 let res = self
426 .poll_inner(|inner, cx| {
427 if inner.runner.is_input_ready() {
428 match inner.runner.input(buf) {
429 Ok(0) => {
430 inner.runner.set_input_waker(cx.waker());
431 Poll::Pending
432 }
433 Ok(n) => Poll::Ready(Ok(n)),
434 Err(e) => Poll::Ready(Err(e)),
435 }
436 } else {
437 inner.runner.set_input_waker(cx.waker());
438 Poll::Pending
439 }
440 })
441 .await;
442 self.wake_progress();
443 res
444 }
445
446 pub(crate) async fn add_channel(
457 &self,
458 handle: ChanHandle,
459 ) -> Result<ChanIO<'_>> {
460 let mut inner = self.inner.lock().await;
461 let num = handle.num();
462 let idx = num.0 as usize;
463 if inner.chan_handles[idx].is_some() {
464 return error::Bug.fail();
465 }
466 inner.chan_handles[idx] = Some(handle);
467
468 debug_assert_eq!(self.chan_refcounts[idx].load(Relaxed), 0);
469 self.chan_refcounts[idx].store(1, Relaxed);
470 Ok(ChanIO::new_normal(num, self))
471 }
472}
473
474#[cfg(feature = "multi-thread")]
476pub(crate) trait MaybeSend: Sync {}
477#[cfg(not(feature = "multi-thread"))]
478pub(crate) trait MaybeSend {}
479
480impl<'a, CS: CliServ> MaybeSend for AsyncSunset<'a, CS> {}
481
482pub(crate) trait ChanCore: MaybeSend {
485 fn inc_chan(&self, num: ChanNum);
486 fn dec_chan(&self, num: ChanNum);
487 fn inc_read_chan(&self, num: ChanNum, dt: ChanData);
488 fn dec_read_chan(&self, num: ChanNum, dt: ChanData);
489
490 fn poll_until_channel_closed(
491 &self,
492 cx: &mut Context,
493 num: ChanNum,
494 ) -> Poll<Result<()>>;
495
496 fn poll_read_channel(
497 &self,
498 cx: &mut Context,
499 num: ChanNum,
500 dt: ChanData,
501 buf: &mut [u8],
502 ) -> Poll<Result<usize>>;
503
504 fn poll_write_channel(
505 &self,
506 cx: &mut Context,
507 num: ChanNum,
508 dt: ChanData,
509 buf: &[u8],
510 ) -> Poll<Result<usize>>;
511
512 fn poll_term_window_change(
514 &self,
515 cx: &mut Context,
516 num: ChanNum,
517 winch: &sunset::packets::WinChange,
518 ) -> Poll<Result<()>>;
519}
520
521impl<'a, CS: CliServ> ChanCore for AsyncSunset<'a, CS> {
522 fn inc_chan(&self, num: ChanNum) {
524 let c = self.chan_refcounts[num.0 as usize].fetch_add(1, Relaxed);
526 debug_assert_ne!(c, 0);
527 debug_assert_ne!(c, usize::MAX);
529 }
530
531 fn dec_chan(&self, num: ChanNum) {
533 let c = self.chan_refcounts[num.0 as usize].fetch_sub(1, AcqRel);
535 debug_assert_ne!(c, 0);
536 if c == 1 {
537 self.wake_progress();
540 }
541 }
542
543 fn inc_read_chan(&self, num: ChanNum, dt: ChanData) {
545 let c = self.chan_readcount(num, dt).fetch_add(1, AcqRel);
546 debug_assert_ne!(c, usize::MAX);
547 }
548
549 fn dec_read_chan(&self, num: ChanNum, dt: ChanData) {
551 let c = self.chan_readcount(num, dt).fetch_sub(1, AcqRel);
552 debug_assert_ne!(c, 0);
553 if c == 1 {
554 self.wake_progress();
557 }
558 }
559
560 fn poll_until_channel_closed(
561 &self,
562 cx: &mut Context,
563 num: ChanNum,
564 ) -> Poll<Result<()>> {
565 let i = self.inner.lock();
567 let i = pin!(i);
568 let Ready(mut inner) = i.poll(cx) else {
569 return Pending;
570 };
571
572 let (runner, h) = inner.fetch(num)?;
573 if runner.is_channel_closed(h) {
574 Poll::Ready(Ok(()))
575 } else {
576 runner.set_channel_read_waker(h, Normal, cx.waker());
578 Poll::Pending
579 }
580 }
581
582 fn poll_read_channel(
584 &self,
585 cx: &mut Context,
586 num: ChanNum,
587 dt: ChanData,
588 buf: &mut [u8],
589 ) -> Poll<Result<usize>> {
590 let i = self.inner.lock();
592 let i = pin!(i);
593 let Ready(mut inner) = i.poll(cx) else {
594 return Pending;
595 };
596
597 let (runner, h) = inner.fetch(num)?;
598 let i = match runner.read_channel(h, dt, buf) {
599 Ok(0) => {
600 trace!("read ch {num:?} dt {dt:?} pending");
602 runner.set_channel_read_waker(h, dt, cx.waker());
603 Poll::Pending
604 }
605 Err(Error::ChannelEOF) => Poll::Ready(Ok(0)),
606 r => {
607 trace!("read ready ch {num:?} dt {dt:?} {r:?}");
608 Poll::Ready(r)
609 }
610 };
611 if matches!(i, Poll::Ready(_)) {
612 self.wake_progress()
613 }
614 i
615 }
616
617 fn poll_write_channel(
618 &self,
619 cx: &mut Context,
620 num: ChanNum,
621 dt: ChanData,
622 buf: &[u8],
623 ) -> Poll<Result<usize>> {
624 if buf.is_empty() {
625 return Poll::Ready(Ok(0));
626 }
627
628 let i = self.inner.lock();
630 let i = pin!(i);
631 let Ready(mut inner) = i.poll(cx) else {
632 return Pending;
633 };
634
635 let (runner, h) = inner.fetch(num)?;
636 let l = runner.write_channel(h, dt, buf);
637 if let Ok(0) = l {
638 trace!("write ch {num:?} dt {dt:?} pending");
640 runner.set_channel_write_waker(h, dt, cx.waker());
641 Poll::Pending
642 } else {
643 trace!("write ready ch {num:?} dt {dt:?} {l:?}");
644 self.wake_progress();
645 Poll::Ready(l)
646 }
647 }
648
649 fn poll_term_window_change(
650 &self,
651 cx: &mut Context,
652 num: ChanNum,
653 winch: &sunset::packets::WinChange,
654 ) -> Poll<Result<()>> {
655 let i = self.inner.lock();
657 let i = pin!(i);
658 let Ready(mut inner) = i.poll(cx) else {
659 return Pending;
660 };
661 let (runner, h) = inner.fetch(num)?;
662 Poll::Ready(runner.term_window_change(h, winch))
663 }
664}