Fix: add protection against receiving or sending of unrealistic TMMBR or Goog-Remb bitrate values.

This commit is contained in:
Simon Morlat 2026-08-03 15:58:37 +02:00 committed by Julien Wadel
parent 833952690a
commit 051c6e7cbc
3 changed files with 37 additions and 19 deletions

View file

@ -41,14 +41,27 @@ void ms_bandwidth_controller_reset_state(MSBandwidthController *obj) {
obj->congestion_detected = 0;
}
static void ms_bandwidth_controller_send_bitrate(MSBandwidthController *obj, struct _MediaStream *stream) {
static void ms_bandwidth_controller_send_bitrate_request(MSBandwidthController *obj, struct _MediaStream *stream) {
RtpSession *session = stream->sessions.rtp_session;
float bandwidth = 0;
size_t num_streams = bctbx_list_size(obj->controlled_streams);
if (num_streams == 0) {
/* This should never happen but let's avoid the fatal division by zero that will follow. */
ms_error("MSBandwidthController[%p]: no controlled streams", obj);
return;
}
if (obj->currently_requested_stream_bandwidth > 0 && obj->maximum_bw_usage > 0 &&
obj->maximum_bw_usage < obj->currently_requested_stream_bandwidth) {
bandwidth = obj->maximum_bw_usage / bctbx_list_size(obj->controlled_streams);
bandwidth = obj->maximum_bw_usage / num_streams;
} else {
bandwidth = obj->currently_requested_stream_bandwidth / bctbx_list_size(obj->controlled_streams);
bandwidth = obj->currently_requested_stream_bandwidth / num_streams;
}
if (bandwidth < 1000) {
ms_warning("MSBandwidthController[%p]: not sending too low bitrate request (%f bit/s)", obj, bandwidth);
return;
}
// Send a goog-remb if the feature is enabled
@ -77,7 +90,7 @@ void ms_bandwidth_controller_set_maximum_bandwidth_usage(MSBandwidthController *
bctbx_list_t *elem;
for (elem = obj->controlled_streams; elem != NULL; elem = elem->next) {
MediaStream *ms = (MediaStream *)elem->data;
ms_bandwidth_controller_send_bitrate(obj, ms);
ms_bandwidth_controller_send_bitrate_request(obj, ms);
}
}
/* If there is not yet currently_requested_stream_bandwidth (means no congestion detected yet and no bandwidth
@ -200,7 +213,7 @@ static void on_congestion_state_changed(const OrtpEventData *evd, void *user_poi
}
obj->currently_requested_stream_bandwidth = controlled_stream_bandwidth_requested;
ms_bandwidth_controller_send_bitrate(obj, ms);
ms_bandwidth_controller_send_bitrate_request(obj, ms);
obj->download_video_bandwidth_available_estimated = 0;
obj->download_audio_bandwidth_available_estimated = 0;
rtp_session_enable_video_bandwidth_estimator(ms->sessions.rtp_session, &video_bandwidth_estimator_params);
@ -236,7 +249,7 @@ static void send_bitrate_for_controlled_video_streams(MSBandwidthController *obj
/* send a TMMBR request for each one of the controlled video streams. */
for (elem = obj->controlled_streams; elem != NULL; elem = elem->next) {
MediaStream *ms = (MediaStream *)elem->data;
ms_bandwidth_controller_send_bitrate(obj, ms);
ms_bandwidth_controller_send_bitrate_request(obj, ms);
}
}
@ -290,7 +303,7 @@ static void on_audio_bandwidth_estimation_available(const OrtpEventData *evd, vo
(int)bctbx_list_size(obj->controlled_streams));
obj->download_audio_bandwidth_available_estimated = estimated_bitrate;
obj->currently_requested_stream_bandwidth = estimated_bitrate;
ms_bandwidth_controller_send_bitrate(obj, ms);
ms_bandwidth_controller_send_bitrate_request(obj, ms);
}
}

View file

@ -1748,7 +1748,7 @@ static int ice_get_componentID_from_rtp_session(const OrtpEventData *evt_data) {
} else if (evt_data->info.socket_type == OrtpRTCPSocket) {
return 2;
}
ms_error("ice: invalid OrtpEventData");
ms_error("ice: invalid OrtpEventData (socket_type=%i)", (int)evt_data->info.socket_type);
return -1;
}
@ -2854,9 +2854,11 @@ static void ice_handle_received_turn_refresh_success_response(IceCheckList *cl,
if (componentID == -1) return;
context = ice_get_turn_context_from_check_list_componentID(cl, componentID);
/* First remove the now terminated STUN transaction */
tr_id = ms_stun_message_get_tr_id(msg);
ice_check_list_remove_stun_server_request(cl, &tr_id);
/* Then Update related TURN context */
context = ice_get_turn_context_from_check_list_componentID(cl, componentID);
if (!context) {
ms_warning("ice: no turn context while receiving refresh success response");
return;

View file

@ -22,7 +22,7 @@
#include "mediastreamer-config.h"
#endif
#include <bctoolbox/defs.h>
#include "bctoolbox/defs.h"
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msrtp.h"
@ -1016,21 +1016,24 @@ static int update_bitrate_limit_from_tmmbr(MediaStream *obj, int br_limit) {
void media_stream_process_tmmbr(MediaStream *ms, uint64_t tmmbr_mxtbr) {
int br_int;
ms_message("MediaStream[%p]: received a TMMBR for bitrate %llu kbits/s", ms,
(unsigned long long)(tmmbr_mxtbr / 1000));
ms_message("MediaStream[%p]: received a TMMBR or Goog-remb for bitrate %f kbits/s", ms,
((float)tmmbr_mxtbr / 1000.0f));
/* When audio estimator is on, the actual output will be increased so reduce the incoming TMMBR */
if (ms->type == MSAudio && media_stream_get_rtp_session(ms)->audio_bandwidth_estimator_enabled &&
media_stream_get_rtp_session(ms)->rtp.audio_bw_estimator) {
tmmbr_mxtbr -=
tmmbr_mxtbr / rtp_session_get_audio_bandwidth_estimator_duplicate_rate(media_stream_get_rtp_session(ms));
}
if (tmmbr_mxtbr < (uint64_t)INT_MAX) {
if (tmmbr_mxtbr < (uint64_t)1000) {
ms_warning("Requested bitrate is too low, ignoring");
return;
} else if (tmmbr_mxtbr < (uint64_t)INT_MAX) {
br_int = (int)tmmbr_mxtbr;
} else {
br_int = INT_MAX;
}
RtpSession *rtp_session = media_stream_get_rtp_session(ms);
/* When audio estimator is on, the actual output will be increased so reduce the incoming TMMBR */
if (ms->type == MSAudio && rtp_session->audio_bandwidth_estimator_enabled && rtp_session->rtp.audio_bw_estimator) {
br_int -= br_int / rtp_session_get_audio_bandwidth_estimator_duplicate_rate(rtp_session);
}
br_int = update_bitrate_limit_from_tmmbr(ms, br_int);
if (br_int == -1) return;