Skip to content

Commit 0acb5a4

Browse files
authored
[sctp] make write sync (#344)
There's no reason for it to be async because it just buffers the data in memory (actual IO is happening in a separate thread).
1 parent 5b79f08 commit 0acb5a4

File tree

11 files changed

+259
-366
lines changed

11 files changed

+259
-366
lines changed

data/src/data_channel/mod.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,7 @@ impl DataChannel {
118118
})
119119
.marshal()?;
120120

121-
stream
122-
.write_sctp(&msg, PayloadProtocolIdentifier::Dcep)
123-
.await?;
121+
stream.write_sctp(&msg, PayloadProtocolIdentifier::Dcep)?;
124122
}
125123
Ok(DataChannel::new(stream, config))
126124
}
@@ -286,13 +284,10 @@ impl DataChannel {
286284
};
287285

288286
let n = if data_len == 0 {
289-
let _ = self
290-
.stream
291-
.write_sctp(&Bytes::from_static(&[0]), ppi)
292-
.await?;
287+
let _ = self.stream.write_sctp(&Bytes::from_static(&[0]), ppi)?;
293288
0
294289
} else {
295-
let n = self.stream.write_sctp(data, ppi).await?;
290+
let n = self.stream.write_sctp(data, ppi)?;
296291
self.bytes_sent.fetch_add(n, Ordering::SeqCst);
297292
n
298293
};
@@ -305,8 +300,7 @@ impl DataChannel {
305300
let ack = Message::DataChannelAck(DataChannelAck {}).marshal()?;
306301
Ok(self
307302
.stream
308-
.write_sctp(&ack, PayloadProtocolIdentifier::Dcep)
309-
.await?)
303+
.write_sctp(&ack, PayloadProtocolIdentifier::Dcep)?)
310304
}
311305

312306
/// Close closes the DataChannel and the underlying SCTP stream.

sctp/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Breaking
6+
7+
* Make `sctp::Stream::write` & `sctp::Stream::write_sctp` sync [#344](https://github.com/webrtc-rs/webrtc/pull/344)
8+
59
## v0.6.2
610

711
* Increased minimum support rust version to `1.60.0`.

sctp/examples/ping.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ async fn main() -> Result<(), Error> {
8383
while ping_seq_num < 10 {
8484
let ping_msg = format!("ping {}", ping_seq_num);
8585
println!("sent: {}", ping_msg);
86-
stream_tx.write(&Bytes::from(ping_msg)).await?;
86+
stream_tx.write(&Bytes::from(ping_msg))?;
8787

8888
ping_seq_num += 1;
8989
}

sctp/examples/pong.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async fn main() -> Result<(), Error> {
8686

8787
let pong_msg = format!("pong [{}]", ping_msg);
8888
println!("sent: {}", pong_msg);
89-
stream2.write(&Bytes::from(pong_msg)).await?;
89+
stream2.write(&Bytes::from(pong_msg))?;
9090

9191
tokio::time::sleep(Duration::from_secs(1)).await;
9292
}

sctp/src/association/association_internal.rs

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ impl AssociationInternal {
351351
) -> Vec<Bytes> {
352352
// Pop unsent data chunks from the pending queue to send as much as
353353
// cwnd and rwnd allow.
354-
let (chunks, sis_to_reset) = self.pop_pending_data_chunks_to_send().await;
354+
let (chunks, sis_to_reset) = self.pop_pending_data_chunks_to_send();
355355
if !chunks.is_empty() {
356356
// Start timer. (noop if already started)
357357
log::trace!("[{}] T3-rtx timer start (pt1)", self.name);
@@ -1771,7 +1771,7 @@ impl AssociationInternal {
17711771
self.handle_peer_last_tsn_and_acknowledgement(false)
17721772
}
17731773

1774-
async fn send_reset_request(&mut self, stream_identifier: u16) -> Result<()> {
1774+
fn send_reset_request(&mut self, stream_identifier: u16) -> Result<()> {
17751775
let state = self.get_state();
17761776
if state != AssociationState::Established {
17771777
return Err(Error::ErrResetPacketInStateNotExist);
@@ -1787,7 +1787,7 @@ impl AssociationInternal {
17871787
..Default::default()
17881788
};
17891789

1790-
self.pending_queue.push(c).await;
1790+
self.pending_queue.push(c);
17911791
self.awake_write_loop();
17921792

17931793
Ok(())
@@ -1852,12 +1852,12 @@ impl AssociationInternal {
18521852
}
18531853

18541854
/// Move the chunk peeked with self.pending_queue.peek() to the inflight_queue.
1855-
async fn move_pending_data_chunk_to_inflight_queue(
1855+
fn move_pending_data_chunk_to_inflight_queue(
18561856
&mut self,
18571857
beginning_fragment: bool,
18581858
unordered: bool,
18591859
) -> Option<ChunkPayloadData> {
1860-
if let Some(mut c) = self.pending_queue.pop(beginning_fragment, unordered).await {
1860+
if let Some(mut c) = self.pending_queue.pop(beginning_fragment, unordered) {
18611861
// Mark all fragements are in-flight now
18621862
if c.ending_fragment {
18631863
c.set_all_inflight();
@@ -1894,70 +1894,68 @@ impl AssociationInternal {
18941894

18951895
/// pop_pending_data_chunks_to_send pops chunks from the pending queues as many as
18961896
/// the cwnd and rwnd allows to send.
1897-
async fn pop_pending_data_chunks_to_send(&mut self) -> (Vec<ChunkPayloadData>, Vec<u16>) {
1897+
fn pop_pending_data_chunks_to_send(&mut self) -> (Vec<ChunkPayloadData>, Vec<u16>) {
18981898
let mut chunks = vec![];
18991899
let mut sis_to_reset = vec![]; // stream identifiers to reset
1900-
let is_empty = self.pending_queue.len() == 0;
1901-
if !is_empty {
1902-
// RFC 4960 sec 6.1. Transmission of DATA Chunks
1903-
// A) At any given time, the data sender MUST NOT transmit new data to
1904-
// any destination transport address if its peer's rwnd indicates
1905-
// that the peer has no buffer space (i.e., rwnd is 0; see Section
1906-
// 6.2.1). However, regardless of the value of rwnd (including if it
1907-
// is 0), the data sender can always have one DATA chunk in flight to
1908-
// the receiver if allowed by cwnd (see rule B, below).
1909-
1910-
while let Some(c) = self.pending_queue.peek().await {
1911-
let (beginning_fragment, unordered, data_len, stream_identifier) = (
1912-
c.beginning_fragment,
1913-
c.unordered,
1914-
c.user_data.len(),
1915-
c.stream_identifier,
1916-
);
19171900

1918-
if data_len == 0 {
1919-
sis_to_reset.push(stream_identifier);
1920-
if self
1921-
.pending_queue
1922-
.pop(beginning_fragment, unordered)
1923-
.await
1924-
.is_none()
1925-
{
1926-
log::error!("failed to pop from pending queue");
1927-
}
1928-
continue;
1929-
}
1901+
if self.pending_queue.len() == 0 {
1902+
return (chunks, sis_to_reset);
1903+
}
19301904

1931-
if self.inflight_queue.get_num_bytes() + data_len > self.cwnd as usize {
1932-
break; // would exceeds cwnd
1933-
}
1905+
// RFC 4960 sec 6.1. Transmission of DATA Chunks
1906+
// A) At any given time, the data sender MUST NOT transmit new data to
1907+
// any destination transport address if its peer's rwnd indicates
1908+
// that the peer has no buffer space (i.e., rwnd is 0; see Section
1909+
// 6.2.1). However, regardless of the value of rwnd (including if it
1910+
// is 0), the data sender can always have one DATA chunk in flight to
1911+
// the receiver if allowed by cwnd (see rule B, below).
1912+
while let Some(c) = self.pending_queue.peek() {
1913+
let (beginning_fragment, unordered, data_len, stream_identifier) = (
1914+
c.beginning_fragment,
1915+
c.unordered,
1916+
c.user_data.len(),
1917+
c.stream_identifier,
1918+
);
19341919

1935-
if data_len > self.rwnd as usize {
1936-
break; // no more rwnd
1920+
if data_len == 0 {
1921+
sis_to_reset.push(stream_identifier);
1922+
if self
1923+
.pending_queue
1924+
.pop(beginning_fragment, unordered)
1925+
.is_none()
1926+
{
1927+
log::error!("failed to pop from pending queue");
19371928
}
1929+
continue;
1930+
}
19381931

1939-
self.rwnd -= data_len as u32;
1932+
if self.inflight_queue.get_num_bytes() + data_len > self.cwnd as usize {
1933+
break; // would exceed cwnd
1934+
}
19401935

1941-
if let Some(chunk) = self
1942-
.move_pending_data_chunk_to_inflight_queue(beginning_fragment, unordered)
1943-
.await
1944-
{
1945-
chunks.push(chunk);
1946-
}
1936+
if data_len > self.rwnd as usize {
1937+
break; // no more rwnd
19471938
}
19481939

1949-
// the data sender can always have one DATA chunk in flight to the receiver
1950-
if chunks.is_empty() && self.inflight_queue.is_empty() {
1951-
// Send zero window probe
1952-
if let Some(c) = self.pending_queue.peek().await {
1953-
let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
1940+
self.rwnd -= data_len as u32;
19541941

1955-
if let Some(chunk) = self
1956-
.move_pending_data_chunk_to_inflight_queue(beginning_fragment, unordered)
1957-
.await
1958-
{
1959-
chunks.push(chunk);
1960-
}
1942+
if let Some(chunk) =
1943+
self.move_pending_data_chunk_to_inflight_queue(beginning_fragment, unordered)
1944+
{
1945+
chunks.push(chunk);
1946+
}
1947+
}
1948+
1949+
// the data sender can always have one DATA chunk in flight to the receiver
1950+
if chunks.is_empty() && self.inflight_queue.is_empty() {
1951+
// Send zero window probe
1952+
if let Some(c) = self.pending_queue.peek() {
1953+
let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
1954+
1955+
if let Some(chunk) =
1956+
self.move_pending_data_chunk_to_inflight_queue(beginning_fragment, unordered)
1957+
{
1958+
chunks.push(chunk);
19611959
}
19621960
}
19631961
}

sctp/src/association/association_internal/association_internal_test.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,8 @@ async fn test_assoc_handle_init() -> Result<()> {
437437
Ok(())
438438
}
439439

440-
#[tokio::test]
441-
async fn test_assoc_max_message_size_default() -> Result<()> {
440+
#[test]
441+
fn test_assoc_max_message_size_default() -> Result<()> {
442442
let mut a = create_association_internal(Config {
443443
net_conn: Arc::new(DumbConn {}),
444444
max_receive_buffer_size: 0,
@@ -458,7 +458,7 @@ async fn test_assoc_max_message_size_default() -> Result<()> {
458458
let p = Bytes::from(vec![0u8; 65537]);
459459
let ppi = PayloadProtocolIdentifier::from(s.default_payload_type.load(Ordering::SeqCst));
460460

461-
if let Err(err) = s.write_sctp(&p.slice(..65536), ppi).await {
461+
if let Err(err) = s.write_sctp(&p.slice(..65536), ppi) {
462462
assert_ne!(
463463
Error::ErrOutboundPacketTooLarge,
464464
err,
@@ -468,7 +468,7 @@ async fn test_assoc_max_message_size_default() -> Result<()> {
468468
assert!(false, "should be error");
469469
}
470470

471-
if let Err(err) = s.write_sctp(&p.slice(..65537), ppi).await {
471+
if let Err(err) = s.write_sctp(&p.slice(..65537), ppi) {
472472
assert_eq!(
473473
Error::ErrOutboundPacketTooLarge,
474474
err,
@@ -482,8 +482,8 @@ async fn test_assoc_max_message_size_default() -> Result<()> {
482482
Ok(())
483483
}
484484

485-
#[tokio::test]
486-
async fn test_assoc_max_message_size_explicit() -> Result<()> {
485+
#[test]
486+
fn test_assoc_max_message_size_explicit() -> Result<()> {
487487
let mut a = create_association_internal(Config {
488488
net_conn: Arc::new(DumbConn {}),
489489
max_receive_buffer_size: 0,
@@ -504,7 +504,7 @@ async fn test_assoc_max_message_size_explicit() -> Result<()> {
504504
let p = Bytes::from(vec![0u8; 30001]);
505505
let ppi = PayloadProtocolIdentifier::from(s.default_payload_type.load(Ordering::SeqCst));
506506

507-
if let Err(err) = s.write_sctp(&p.slice(..30000), ppi).await {
507+
if let Err(err) = s.write_sctp(&p.slice(..30000), ppi) {
508508
assert_ne!(
509509
Error::ErrOutboundPacketTooLarge,
510510
err,
@@ -514,7 +514,7 @@ async fn test_assoc_max_message_size_explicit() -> Result<()> {
514514
assert!(false, "should be error");
515515
}
516516

517-
if let Err(err) = s.write_sctp(&p.slice(..30001), ppi).await {
517+
if let Err(err) = s.write_sctp(&p.slice(..30001), ppi) {
518518
assert_eq!(
519519
Error::ErrOutboundPacketTooLarge,
520520
err,

0 commit comments

Comments
 (0)