Skip to content

Commit cbfd303

Browse files
authored
[turn] release UDP port once Allocation is gone (webrtc-rs#330)
On our servers, we found that after the TURN service runs for a long time, there will be a large number of UDP ports that are not released. We found that the reason is that after the `packet_handler` task is started, if the client no longer uses the UDP connection, `relay_socket.recv_from` will never return. So we add a 10-second timeout here to check whether the allocation has been dropped every 10 seconds. Fixes webrtc-rs#232 Refs webrtc-rs/turn#13
1 parent 0a16ad2 commit cbfd303

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

turn/CHANGELOG.md

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

33
## Unreleased
44

5+
* [#330 Fix the problem that the UDP port of the server relay is not released](https://github.com/webrtc-rs/webrtc/pull/330) by [@clia](https://github.com/clia).
6+
57
## v0.6.1
68

79
* Added `delete_allocations_by_username` method on `Server`. This method provides possibility to manually delete allocation [#263](https://github.com/webrtc-rs/webrtc/pull/263) by [@logist322](https://github.com/logist322).

turn/src/allocation/mod.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ use std::{
2424
sync::{atomic::AtomicBool, atomic::Ordering, Arc},
2525
};
2626
use tokio::{
27-
sync::{mpsc, Mutex},
27+
sync::{
28+
mpsc,
29+
oneshot::{self, Sender},
30+
Mutex,
31+
},
2832
time::{Duration, Instant},
2933
};
3034

@@ -78,6 +82,7 @@ pub struct Allocation {
7882
timer_expired: Arc<AtomicBool>,
7983
closed: AtomicBool, // Option<mpsc::Receiver<()>>,
8084
pub(crate) relayed_bytes: AtomicUsize,
85+
drop_tx: Option<Sender<u32>>,
8186
}
8287

8388
fn addr2ipfingerprint(addr: &SocketAddr) -> String {
@@ -107,6 +112,7 @@ impl Allocation {
107112
timer_expired: Arc::new(AtomicBool::new(false)),
108113
closed: AtomicBool::new(false),
109114
relayed_bytes: Default::default(),
115+
drop_tx: None,
110116
}
111117
}
112118

@@ -313,26 +319,38 @@ impl Allocation {
313319
// datagram, and the XOR-PEER-ADDRESS attribute is set to the source
314320
// transport address of the received UDP datagram. The Data indication
315321
// is then sent on the 5-tuple associated with the allocation.
316-
async fn packet_handler(&self) {
322+
async fn packet_handler(&mut self) {
317323
let five_tuple = self.five_tuple;
318324
let relay_addr = self.relay_addr;
319325
let relay_socket = Arc::clone(&self.relay_socket);
320326
let turn_socket = Arc::clone(&self.turn_socket);
321327
let allocations = self.allocations.clone();
322328
let channel_bindings = Arc::clone(&self.channel_bindings);
323329
let permissions = Arc::clone(&self.permissions);
330+
let (drop_tx, drop_rx) = oneshot::channel::<u32>();
331+
self.drop_tx = Some(drop_tx);
324332

325333
tokio::spawn(async move {
326334
let mut buffer = vec![0u8; RTP_MTU];
327335

336+
tokio::pin!(drop_rx);
337+
328338
loop {
329-
let (n, src_addr) = match relay_socket.recv_from(&mut buffer).await {
330-
Ok((n, src_addr)) => (n, src_addr),
331-
Err(_) => {
332-
if let Some(allocs) = &allocations {
333-
let mut alls = allocs.lock().await;
334-
alls.remove(&five_tuple);
339+
let (n, src_addr) = tokio::select! {
340+
result = relay_socket.recv_from(&mut buffer) => {
341+
match result {
342+
Ok((n, src_addr)) => (n, src_addr),
343+
Err(_) => {
344+
if let Some(allocs) = &allocations {
345+
let mut alls = allocs.lock().await;
346+
alls.remove(&five_tuple);
347+
}
348+
break;
349+
}
335350
}
351+
}
352+
_ = drop_rx.as_mut() => {
353+
log::trace!("allocation has stopped, stop packet_handler. five_tuple: {:?}", five_tuple);
336354
break;
337355
}
338356
};

0 commit comments

Comments
 (0)