Skip to content

Commit c4bb63f

Browse files
committed
refactor Rtc::do_poll_output so it's called in a loop, rather then calling itself recursively.
This avoids a stack overflow in the `data_channel_flood` unit test
1 parent ac7502d commit c4bb63f

1 file changed

Lines changed: 25 additions & 21 deletions

File tree

src/lib.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,11 @@ impl Rtc {
15311531
///
15321532
/// See [`Rtc`] instance documentation for how this is expected to be used in a loop.
15331533
pub fn poll_output(&mut self) -> Result<Output, RtcError> {
1534-
let o = self.do_poll_output()?;
1534+
let o = loop {
1535+
if let Some(o) = self.do_poll_output()? {
1536+
break o;
1537+
}
1538+
};
15351539

15361540
match &o {
15371541
Output::Event(e) => match e {
@@ -1559,10 +1563,10 @@ impl Rtc {
15591563
Ok(o)
15601564
}
15611565

1562-
fn do_poll_output(&mut self) -> Result<Output, RtcError> {
1566+
fn do_poll_output(&mut self) -> Result<Option<Output>, RtcError> {
15631567
if !self.alive {
15641568
self.last_timeout_reason = Reason::NotHappening;
1565-
return Ok(Output::Timeout(not_happening()));
1569+
return Ok(Some(Output::Timeout(not_happening())));
15661570
}
15671571

15681572
if self.closing {
@@ -1583,14 +1587,14 @@ impl Rtc {
15831587
destination: send.destination,
15841588
contents,
15851589
};
1586-
return Ok(Output::Transmit(t));
1590+
return Ok(Some(Output::Transmit(t)));
15871591
}
15881592
}
15891593

15901594
// All packets drained — mark as not alive
15911595
self.alive = false;
15921596
self.last_timeout_reason = Reason::NotHappening;
1593-
return Ok(Output::Timeout(not_happening()));
1597+
return Ok(Some(Output::Timeout(not_happening())));
15941598
}
15951599

15961600
while let Some(e) = self.ice.poll_event() {
@@ -1599,7 +1603,7 @@ impl Rtc {
15991603
//
16001604
}
16011605
IceAgentEvent::IceConnectionStateChange(v) => {
1602-
return Ok(Output::Event(Event::IceConnectionStateChange(v)));
1606+
return Ok(Some(Output::Event(Event::IceConnectionStateChange(v))));
16031607
}
16041608
IceAgentEvent::DiscoveredRecv { proto, source } => {
16051609
debug!("ICE remote address: {:?}/{:?}", Pii(source), proto);
@@ -1692,7 +1696,7 @@ impl Rtc {
16921696
break;
16931697
}
16941698
DtlsOutput::CloseNotify => {
1695-
return Ok(Output::Event(Event::Closed));
1699+
return Ok(Some(Output::Event(Event::Closed)));
16961700
}
16971701
other => {
16981702
return Err(RtcError::Dtls(DtlsError::Io(std::io::Error::other(
@@ -1703,7 +1707,7 @@ impl Rtc {
17031707
}
17041708

17051709
if just_connected {
1706-
return Ok(Output::Event(Event::Connected));
1710+
return Ok(Some(Output::Event(Event::Connected)));
17071711
}
17081712

17091713
while let Some(e) = self.sctp.poll() {
@@ -1728,62 +1732,62 @@ impl Rtc {
17281732

17291733
// Run again since this would feed the DTLS subsystem
17301734
// to produce a packet now.
1731-
return self.do_poll_output();
1735+
return Ok(None);
17321736
}
17331737
}
17341738
SctpEvent::Open { id, label } => {
17351739
self.chan.ensure_channel_id_for(id);
17361740
let id = self.chan.channel_id_by_stream_id(id).unwrap();
1737-
return Ok(Output::Event(Event::ChannelOpen(id, label)));
1741+
return Ok(Some(Output::Event(Event::ChannelOpen(id, label))));
17381742
}
17391743
SctpEvent::Close { id } => {
17401744
let Some(id) = self.chan.channel_id_by_stream_id(id) else {
17411745
warn!("Drop ChannelClose event for id: {:?}", id);
17421746
continue;
17431747
};
17441748
self.chan.remove_channel(id, self.last_now);
1745-
return Ok(Output::Event(Event::ChannelClose(id)));
1749+
return Ok(Some(Output::Event(Event::ChannelClose(id))));
17461750
}
17471751
SctpEvent::AssociationLost => {
1748-
return Ok(Output::Event(Event::Closed));
1752+
return Ok(Some(Output::Event(Event::Closed)));
17491753
}
17501754
SctpEvent::Data { id, binary, data } => {
17511755
let Some(id) = self.chan.channel_id_by_stream_id(id) else {
17521756
warn!("Drop ChannelData event for id: {:?}", id);
17531757
continue;
17541758
};
17551759
let cd = ChannelData { id, binary, data };
1756-
return Ok(Output::Event(Event::ChannelData(cd)));
1760+
return Ok(Some(Output::Event(Event::ChannelData(cd))));
17571761
}
17581762
SctpEvent::BufferedAmountLow { id } => {
17591763
let Some(id) = self.chan.channel_id_by_stream_id(id) else {
17601764
warn!("Drop BufferedAmountLow for id: {:?}", id);
17611765
continue;
17621766
};
1763-
return Ok(Output::Event(Event::ChannelBufferedAmountLow(id)));
1767+
return Ok(Some(Output::Event(Event::ChannelBufferedAmountLow(id))));
17641768
}
17651769
}
17661770
}
17671771

17681772
if let Some(ev) = self.session.poll_event() {
1769-
return Ok(Output::Event(ev));
1773+
return Ok(Some(Output::Event(ev)));
17701774
}
17711775

17721776
// Some polling needs to bubble up errors.
17731777
if let Some(ev) = self.session.poll_event_fallible()? {
1774-
return Ok(Output::Event(ev));
1778+
return Ok(Some(Output::Event(ev)));
17751779
}
17761780

17771781
if let Some(e) = self.stats.as_mut().and_then(|s| s.poll_output()) {
1778-
return Ok(match e {
1782+
return Ok(Some(match e {
17791783
StatsEvent::Peer(s) => Output::Event(Event::PeerStats(s)),
17801784
StatsEvent::MediaIngress(s) => Output::Event(Event::MediaIngressStats(s)),
17811785
StatsEvent::MediaEgress(s) => Output::Event(Event::MediaEgressStats(s)),
1782-
});
1786+
}));
17831787
}
17841788

17851789
if let Some(v) = self.ice.poll_transmit() {
1786-
return Ok(Output::Transmit(v));
1790+
return Ok(Some(Output::Transmit(v)));
17871791
}
17881792

17891793
if let Some(send) = &self.send_addr {
@@ -1799,7 +1803,7 @@ impl Rtc {
17991803
destination: send.destination,
18001804
contents,
18011805
};
1802-
return Ok(Output::Transmit(t));
1806+
return Ok(Some(Output::Transmit(t)));
18031807
}
18041808
} else {
18051809
// Don't allow accumulated feedback to build up indefinitely
@@ -1830,7 +1834,7 @@ impl Rtc {
18301834

18311835
self.last_timeout_reason = reason;
18321836

1833-
Ok(Output::Timeout(next))
1837+
Ok(Some(Output::Timeout(next)))
18341838
}
18351839

18361840
/// The reason for the last [`Output::Timeout`]

0 commit comments

Comments
 (0)