webrtc icon indicating copy to clipboard operation
webrtc copied to clipboard

Udp connection not close when using TURN (reopen #195)

Open shiqifeng2000 opened this issue 2 years ago • 1 comments

hi

This is a bug similar to bug 195, the out come is udp port not closing.

It seems when I try to deploy a TURN server, the candidate would use the related_address to communicate with the TURN server. But when the peer connection is dropping and all candidate are dropped, it seems the related_address is still trying to listen to the opened port.

Everytime I opened a new peerconnection, a new port shall be unreleased. It is a sure to come issue, could you please take a look into it?

Screen Shot 2022-08-08 at 10 37 09 AM
[Rolling] 2022-08-08T10:36:37.769958+08:00 - INFO - 1339329739 - Ice candidate Some(
    RTCIceCandidate {
        stats_id: "candidate:7nc6VphUbPm3n0qLtV5oRUfCXOr/auPt",
        foundation: "2842371988",
        priority: 16777215,
        address: "0.0.0.0",
        protocol: Udp,
        port: 55933,
        typ: Relay,
        component: 1,
        related_address: "0.0.0.0",
        related_port: 54677,
        tcp_type: "unspecified",
    },
)

shiqifeng2000 avatar Aug 08 '22 02:08 shiqifeng2000

UPDATE: It seems I have target the problem, you see, in the submodule TURN crate, when agent_gather is starting to gather relay candidate by invoking gather_candidates_relay a TURN client is created to listen to the remote turn socket.

In the listen method of the TURN client, I found a tokio task spawn to listen to that socket, without safe guarding

tokio::spawn(async move {
            let mut buf = vec![0u8; MAX_DATA_BUFFER_SIZE];
            loop {
                //TODO: gracefully exit loop
                let (n, from) = match conn.recv_from(&mut buf).await {
                    Ok((n, from)) => (n, from),
                    Err(err) => {
                        log::debug!("exiting read loop: {}", err);
                        break;
                    }
                };

                log::debug!("received {} bytes of udp from {}", n, from);

                if let Err(err) = ClientInternal::handle_inbound(
                    &read_ch_tx,
                    &buf[..n],
                    from,
                    &stun_serv_str,
                    &tr_map,
                    &binding_mgr,
                )
                .await
                {
                    log::debug!("exiting read loop: {}", err);
                    break;
                }
            }
        });

So, similarly, I play the timeout strategy,

tokio::spawn(async move {
            let mut buf = vec![0u8; MAX_DATA_BUFFER_SIZE];
            loop {
                //TODO: gracefully exit loop
                let timeout = tokio::time::sleep(std::time::Duration::from_secs(10));
                tokio::pin!(timeout);
                let (n, from) = tokio::select! {
                    _ = timeout.as_mut() =>{
                        log::debug!("timeout reading, exiting read loop");
                        break;
                    }
                    result = conn.recv_from(&mut buf)=> {
                        match result {
                            Ok((n, from)) => (n, from),
                            Err(err) => {
                                log::debug!("exiting read loop: {}", err);
                                break;
                            }
                        }
                    }
                };

and it seems the conn got dropped and port released, I am not sure if a Strong/Weak Atomic count could work this time

shiqifeng2000 avatar Aug 08 '22 07:08 shiqifeng2000

Is this issue https://github.com/webrtc-rs/turn/issues/13 the same cause of this one?

clia avatar Oct 15 '22 03:10 clia