Skip to content

Commit c247846

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 6ff567a commit c247846

1 file changed

Lines changed: 24 additions & 20 deletions

File tree

src/lib.rs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,7 +1544,11 @@ impl Rtc {
15441544
///
15451545
/// See [`Rtc`] instance documentation for how this is expected to be used in a loop.
15461546
pub fn poll_output(&mut self) -> Result<Output, RtcError> {
1547-
let o = self.do_poll_output()?;
1547+
let o = loop {
1548+
if let Some(o) = self.do_poll_output()? {
1549+
break o;
1550+
}
1551+
};
15481552

15491553
match &o {
15501554
Output::Event(e) => match e {
@@ -1572,10 +1576,10 @@ impl Rtc {
15721576
Ok(o)
15731577
}
15741578

1575-
fn do_poll_output(&mut self) -> Result<Output, RtcError> {
1579+
fn do_poll_output(&mut self) -> Result<Option<Output>, RtcError> {
15761580
if self.state == RtcState::Closed {
15771581
self.last_timeout_reason = Reason::NotHappening;
1578-
return Ok(Output::Timeout(not_happening()));
1582+
return Ok(Some(Output::Timeout(not_happening())));
15791583
}
15801584

15811585
while let Some(e) = self.ice.poll_event() {
@@ -1584,7 +1588,7 @@ impl Rtc {
15841588
//
15851589
}
15861590
IceAgentEvent::IceConnectionStateChange(v) => {
1587-
return Ok(Output::Event(Event::IceConnectionStateChange(v)));
1591+
return Ok(Some(Output::Event(Event::IceConnectionStateChange(v))));
15881592
}
15891593
IceAgentEvent::DiscoveredRecv { proto, source } => {
15901594
debug!("ICE remote address: {:?}/{:?}", Pii(source), proto);
@@ -1678,7 +1682,7 @@ impl Rtc {
16781682
}
16791683
DtlsOutput::CloseNotify => {
16801684
self.start_close()?;
1681-
return Ok(Output::Event(Event::Closed));
1685+
return Ok(Some(Output::Event(Event::Closed)));
16821686
}
16831687
other => {
16841688
return Err(RtcError::Dtls(DtlsError::Io(std::io::Error::other(
@@ -1689,7 +1693,7 @@ impl Rtc {
16891693
}
16901694

16911695
if just_connected {
1692-
return Ok(Output::Event(Event::Connected));
1696+
return Ok(Some(Output::Event(Event::Connected)));
16931697
}
16941698

16951699
while let Some(e) = self.sctp.poll() {
@@ -1723,63 +1727,63 @@ impl Rtc {
17231727

17241728
// Run again since this would feed the DTLS subsystem
17251729
// to produce a packet now.
1726-
return self.do_poll_output();
1730+
return Ok(None);
17271731
}
17281732
}
17291733
SctpEvent::Open { id, label } => {
17301734
self.chan.ensure_channel_id_for(id);
17311735
let id = self.chan.channel_id_by_stream_id(id).unwrap();
1732-
return Ok(Output::Event(Event::ChannelOpen(id, label)));
1736+
return Ok(Some(Output::Event(Event::ChannelOpen(id, label))));
17331737
}
17341738
SctpEvent::Close { id } => {
17351739
let Some(id) = self.chan.channel_id_by_stream_id(id) else {
17361740
warn!("Drop ChannelClose event for id: {:?}", id);
17371741
continue;
17381742
};
17391743
self.chan.remove_channel(id, self.last_now);
1740-
return Ok(Output::Event(Event::ChannelClose(id)));
1744+
return Ok(Some(Output::Event(Event::ChannelClose(id))));
17411745
}
17421746
SctpEvent::AssociationLost => {
17431747
self.start_close()?;
1744-
return Ok(Output::Event(Event::Closed));
1748+
return Ok(Some(Output::Event(Event::Closed)));
17451749
}
17461750
SctpEvent::Data { id, binary, data } => {
17471751
let Some(id) = self.chan.channel_id_by_stream_id(id) else {
17481752
warn!("Drop ChannelData event for id: {:?}", id);
17491753
continue;
17501754
};
17511755
let cd = ChannelData { id, binary, data };
1752-
return Ok(Output::Event(Event::ChannelData(cd)));
1756+
return Ok(Some(Output::Event(Event::ChannelData(cd))));
17531757
}
17541758
SctpEvent::BufferedAmountLow { id } => {
17551759
let Some(id) = self.chan.channel_id_by_stream_id(id) else {
17561760
warn!("Drop BufferedAmountLow for id: {:?}", id);
17571761
continue;
17581762
};
1759-
return Ok(Output::Event(Event::ChannelBufferedAmountLow(id)));
1763+
return Ok(Some(Output::Event(Event::ChannelBufferedAmountLow(id))));
17601764
}
17611765
}
17621766
}
17631767

17641768
if let Some(ev) = self.session.poll_event() {
1765-
return Ok(Output::Event(ev));
1769+
return Ok(Some(Output::Event(ev)));
17661770
}
17671771

17681772
// Some polling needs to bubble up errors.
17691773
if let Some(ev) = self.session.poll_event_fallible()? {
1770-
return Ok(Output::Event(ev));
1774+
return Ok(Some(Output::Event(ev)));
17711775
}
17721776

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

17811785
if let Some(v) = self.ice.poll_transmit() {
1782-
return Ok(Output::Transmit(v));
1786+
return Ok(Some(Output::Transmit(v)));
17831787
}
17841788

17851789
if let Some(send) = &self.send_addr {
@@ -1795,7 +1799,7 @@ impl Rtc {
17951799
destination: send.destination,
17961800
contents,
17971801
};
1798-
return Ok(Output::Transmit(t));
1802+
return Ok(Some(Output::Transmit(t)));
17991803
}
18001804
} else {
18011805
// Don't allow accumulated feedback to build up indefinitely
@@ -1827,11 +1831,11 @@ impl Rtc {
18271831
if self.state == RtcState::Closing && self.close_drain_complete() {
18281832
self.state = RtcState::Closed;
18291833
self.last_timeout_reason = Reason::NotHappening;
1830-
return Ok(Output::Timeout(not_happening()));
1834+
return Ok(Some(Output::Timeout(not_happening())));
18311835
}
18321836

18331837
self.last_timeout_reason = reason;
1834-
Ok(Output::Timeout(next))
1838+
Ok(Some(Output::Timeout(next)))
18351839
}
18361840

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

0 commit comments

Comments
 (0)