aboutsummaryrefslogtreecommitdiff
path: root/embassy-net-ppp/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-08-25 15:39:25 +0200
committerDario Nieuwenhuis <[email protected]>2023-08-25 20:45:23 +0200
commit2303382dfd6f4e6275a699b938f465a1e6170449 (patch)
tree3c06363a7629347a9ee943d8ad67994606b32bfa /embassy-net-ppp/src
parentaacf14b62a28277599871edf74106b1cd2e01795 (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.rs82
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;
8use core::convert::Infallible; 8use core::convert::Infallible;
9use core::mem::MaybeUninit; 9use core::mem::MaybeUninit;
10 10
11use embassy_futures::select::{select3, Either3}; 11use embassy_futures::select::{select, Either};
12use embassy_net_driver_channel as ch; 12use embassy_net_driver_channel as ch;
13use embassy_net_driver_channel::driver::LinkState; 13use embassy_net_driver_channel::driver::LinkState;
14use embassy_sync::blocking_mutex::raw::NoopRawMutex;
15use embassy_sync::signal::Signal;
16use embedded_io_async::{BufRead, Write, WriteAllError}; 14use embedded_io_async::{BufRead, Write, WriteAllError};
17use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; 15use 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 }