From 91ad87356b2c28279991be7cce5f88f334dd740e Mon Sep 17 00:00:00 2001 From: Jakub Pisarek <99591440+sgfn@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:44:07 +0200 Subject: [PATCH] Buffer RT(C)P packets that arrive pre-DTLS handshake completion due to jitter --- lib/ex_webrtc/dtls_transport.ex | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/ex_webrtc/dtls_transport.ex b/lib/ex_webrtc/dtls_transport.ex index 535652c..a066d12 100644 --- a/lib/ex_webrtc/dtls_transport.ex +++ b/lib/ex_webrtc/dtls_transport.ex @@ -108,6 +108,7 @@ defmodule ExWebRTC.DTLSTransport do ice_connected: false, buffered_local_packets: nil, buffered_remote_packets: nil, + buffered_remote_rtp_packets: [], cert: cert, base64_cert: Base.encode64(cert), pkey: pkey, @@ -341,6 +342,7 @@ defmodule ExWebRTC.DTLSTransport do if peer_fingerprint == state.peer_fingerprint do :ok = setup_srtp(state, lkm, rkm, profile) state = update_dtls_state(state, :connected) + state = flush_buffered_remote_rtp_packets(state) {:ok, state} else Logger.debug("Non-matching peer cert fingerprint.") @@ -352,6 +354,7 @@ defmodule ExWebRTC.DTLSTransport do Logger.debug("DTLS handshake finished") :ok = setup_srtp(state, lkm, rkm, profile) state = update_dtls_state(state, :connected) + state = flush_buffered_remote_rtp_packets(state) state = update_remote_cert_info(state) {:ok, state} @@ -384,11 +387,13 @@ defmodule ExWebRTC.DTLSTransport do {:ok, state} end - defp handle_ice_data({:data, _data}, state) do - Logger.warning( - "Received RTP/RTCP packets, but DTLS handshake hasn't been finished yet. Ignoring." - ) + defp handle_ice_data({:data, data}, state) do + Logger.debug(""" + Received RTP/RTCP packets, but DTLS handshake hasn't been finished yet. \ + They will be processed after the completion of the handshake.\ + """) + state = %{state | buffered_remote_rtp_packets: state.buffered_remote_rtp_packets ++ [data]} {:ok, state} end @@ -433,5 +438,15 @@ defmodule ExWebRTC.DTLSTransport do %{state | remote_cert: cert, remote_base64_cert: base64_cert, remote_fingerprint: fingerprint} end + defp flush_buffered_remote_rtp_packets(%{buffered_remote_rtp_packets: []} = state), do: state + + defp flush_buffered_remote_rtp_packets(state) do + for data <- state.buffered_remote_rtp_packets do + send(self(), {:ex_ice, state.ice_pid, {:data, data}}) + end + + %{state | buffered_remote_rtp_packets: []} + end + defp notify(dst, msg), do: send(dst, {:dtls_transport, self(), msg}) end