diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-08-25 15:39:25 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-08-25 20:45:23 +0200 |
| commit | 2303382dfd6f4e6275a699b938f465a1e6170449 (patch) | |
| tree | 3c06363a7629347a9ee943d8ad67994606b32bfa /embassy-net-ppp/src | |
| parent | aacf14b62a28277599871edf74106b1cd2e01795 (diff) | |
net-ppp: nicer processing loop structure that can't deadlock.
Diffstat (limited to 'embassy-net-ppp/src')
| -rw-r--r-- | embassy-net-ppp/src/lib.rs | 82 |
1 files changed, 40 insertions, 42 deletions
diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs index 7853e04ab..af216c967 100644 --- a/embassy-net-ppp/src/lib.rs +++ b/embassy-net-ppp/src/lib.rs | |||
| @@ -8,11 +8,9 @@ mod fmt; | |||
| 8 | use core::convert::Infallible; | 8 | use core::convert::Infallible; |
| 9 | use core::mem::MaybeUninit; | 9 | use core::mem::MaybeUninit; |
| 10 | 10 | ||
| 11 | use embassy_futures::select::{select3, Either3}; | 11 | use embassy_futures::select::{select, Either}; |
| 12 | use embassy_net_driver_channel as ch; | 12 | use embassy_net_driver_channel as ch; |
| 13 | use embassy_net_driver_channel::driver::LinkState; | 13 | use embassy_net_driver_channel::driver::LinkState; |
| 14 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 15 | use embassy_sync::signal::Signal; | ||
| 16 | use embedded_io_async::{BufRead, Write, WriteAllError}; | 14 | use embedded_io_async::{BufRead, Write, WriteAllError}; |
| 17 | use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; | 15 | use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; |
| 18 | 16 | ||
| @@ -75,59 +73,59 @@ impl<'d, R: BufRead, W: Write> Runner<'d, R, W> { | |||
| 75 | let mut rx_buf = [0; 2048]; | 73 | let mut rx_buf = [0; 2048]; |
| 76 | let mut tx_buf = [0; 2048]; | 74 | let mut tx_buf = [0; 2048]; |
| 77 | 75 | ||
| 78 | let poll_signal: Signal<NoopRawMutex, ()> = Signal::new(); | 76 | let mut needs_poll = true; |
| 79 | poll_signal.signal(()); | ||
| 80 | 77 | ||
| 81 | loop { | 78 | loop { |
| 82 | let mut poll = false; | 79 | let rx_fut = async { |
| 83 | match select3(self.r.fill_buf(), tx_chan.tx_buf(), poll_signal.wait()).await { | 80 | let buf = rx_chan.rx_buf().await; |
| 84 | Either3::First(r) => { | 81 | let rx_data = match needs_poll { |
| 85 | let data = r.map_err(RunError::Read)?; | 82 | true => &[][..], |
| 86 | if data.is_empty() { | 83 | false => match self.r.fill_buf().await { |
| 87 | return Err(RunError::Eof); | 84 | Ok(rx_data) if rx_data.len() == 0 => return Err(RunError::Eof), |
| 88 | } | 85 | Ok(rx_data) => rx_data, |
| 89 | let n = ppp.consume(data, &mut rx_buf); | 86 | Err(e) => return Err(RunError::Read(e)), |
| 87 | }, | ||
| 88 | }; | ||
| 89 | Ok((buf, rx_data)) | ||
| 90 | }; | ||
| 91 | let tx_fut = tx_chan.tx_buf(); | ||
| 92 | match select(rx_fut, tx_fut).await { | ||
| 93 | Either::First(r) => { | ||
| 94 | needs_poll = false; | ||
| 95 | |||
| 96 | let (buf, rx_data) = r?; | ||
| 97 | let n = ppp.consume(rx_data, &mut rx_buf); | ||
| 90 | self.r.consume(n); | 98 | self.r.consume(n); |
| 91 | poll = true; | 99 | |
| 92 | } | 100 | match ppp.poll(&mut tx_buf, &mut rx_buf) { |
| 93 | Either3::Second(pkt) => { | 101 | PPPoSAction::None => {} |
| 94 | match ppp.send(pkt, &mut tx_buf) { | 102 | PPPoSAction::Received(rg) => { |
| 95 | Ok(n) => match self.w.write_all(&tx_buf[..n]).await { | 103 | let pkt = &rx_buf[rg]; |
| 104 | buf[..pkt.len()].copy_from_slice(pkt); | ||
| 105 | rx_chan.rx_done(pkt.len()); | ||
| 106 | } | ||
| 107 | PPPoSAction::Transmit(n) => match self.w.write_all(&tx_buf[..n]).await { | ||
| 96 | Ok(()) => {} | 108 | Ok(()) => {} |
| 97 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), | 109 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), |
| 98 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), | 110 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), |
| 99 | }, | 111 | }, |
| 100 | Err(BufferFullError) => unreachable!(), | ||
| 101 | } | 112 | } |
| 102 | tx_chan.tx_done(); | ||
| 103 | } | ||
| 104 | Either3::Third(_) => poll = true, | ||
| 105 | } | ||
| 106 | 113 | ||
| 107 | if poll { | 114 | match ppp.status().phase { |
| 108 | match ppp.poll(&mut tx_buf, &mut rx_buf) { | 115 | ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), |
| 109 | PPPoSAction::None => {} | 116 | _ => state_chan.set_link_state(LinkState::Down), |
| 110 | PPPoSAction::Received(rg) => { | ||
| 111 | let pkt = &rx_buf[rg]; | ||
| 112 | let buf = rx_chan.rx_buf().await; // TODO: fix possible deadlock | ||
| 113 | buf[..pkt.len()].copy_from_slice(pkt); | ||
| 114 | rx_chan.rx_done(pkt.len()); | ||
| 115 | |||
| 116 | poll_signal.signal(()); | ||
| 117 | } | 117 | } |
| 118 | PPPoSAction::Transmit(n) => { | 118 | } |
| 119 | match self.w.write_all(&tx_buf[..n]).await { | 119 | Either::Second(pkt) => { |
| 120 | match ppp.send(pkt, &mut tx_buf) { | ||
| 121 | Ok(n) => match self.w.write_all(&tx_buf[..n]).await { | ||
| 120 | Ok(()) => {} | 122 | Ok(()) => {} |
| 121 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), | 123 | Err(WriteAllError::WriteZero) => return Err(RunError::WriteZero), |
| 122 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), | 124 | Err(WriteAllError::Other(e)) => return Err(RunError::Write(e)), |
| 123 | } | 125 | }, |
| 124 | poll_signal.signal(()); | 126 | Err(BufferFullError) => unreachable!(), |
| 125 | } | 127 | } |
| 126 | } | 128 | tx_chan.tx_done(); |
| 127 | |||
| 128 | match ppp.status().phase { | ||
| 129 | ppproto::Phase::Open => state_chan.set_link_state(LinkState::Up), | ||
| 130 | _ => state_chan.set_link_state(LinkState::Down), | ||
| 131 | } | 129 | } |
| 132 | } | 130 | } |
| 133 | } | 131 | } |
