diff --git a/daemon/media_socket.c b/daemon/media_socket.c index a524a4c6d..fb7f1a215 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1158,7 +1158,8 @@ static void reset_ps_kernel_stats(struct packet_stream *ps) { /* called with in_lock held */ // sink_handler can be NULL static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *outputs, - struct packet_stream *stream, struct sink_handler *sink_handler, GQueue *sinks) + struct packet_stream *stream, struct sink_handler *sink_handler, GQueue *sinks, + GList **payload_types) { struct rtpengine_destination_info *redi = NULL; struct call *call = stream->call; @@ -1240,13 +1241,15 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out ZERO(stream->kernel_stats); if (proto_is_rtp(media->protocol) && sinks && sinks->length) { - GList *values, *l; + GList *l; struct rtp_stats *rs; reti->rtp = 1; - values = g_hash_table_get_values(stream->rtp_stats); - values = g_list_sort(values, __rtp_stats_pt_sort); - for (l = values; l; l = l->next) { + // this code is execute only once: list therefore must be empty + assert(*payload_types == NULL); + *payload_types = g_hash_table_get_values(stream->rtp_stats); + *payload_types = g_list_sort(*payload_types, __rtp_stats_pt_sort); + for (l = *payload_types; l; ) { if (reti->num_payload_types >= G_N_ELEMENTS(reti->payload_types)) { ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Too many RTP payload types for kernel module"); break; @@ -1270,8 +1273,14 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out can_kernelize = false; break; } - if (!can_kernelize) + if (!can_kernelize) { + // ensure that the final list in *payload_types reflects the payload + // types populated in reti->payload_types + GList *next = l->next; + *payload_types = g_list_delete_link(*payload_types, l); + l = next; continue; + } struct rtpengine_payload_type *rpt = &reti->payload_types[reti->num_payload_types++]; rpt->pt_num = rs->payload_type; @@ -1283,8 +1292,9 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out rpt->replace_pattern_len = replace_pattern.len; memcpy(rpt->replace_pattern, replace_pattern.s, replace_pattern.len); } + + l = l->next; } - g_list_free(values); } else { if (sink_handler && sink_handler->attrs.transcoding) @@ -1374,10 +1384,11 @@ void kernelize(struct packet_stream *stream) { struct rtpengine_target_info reti; ZERO(reti); // reti.local.family determines if anything can be done GQueue outputs = G_QUEUE_INIT; + GList *payload_types = NULL; if (!sinks->length) { // add blackhole kernel rule - const char *err = kernelize_one(&reti, &outputs, stream, NULL, NULL); + const char *err = kernelize_one(&reti, &outputs, stream, NULL, NULL, &payload_types); if (err) ilog(LOG_WARNING, "No support for kernel packet forwarding available (%s)", err); } @@ -1387,12 +1398,14 @@ void kernelize(struct packet_stream *stream) { struct packet_stream *sink = sh->sink; if (PS_ISSET(sink, NAT_WAIT) && !PS_ISSET(sink, RECEIVED)) continue; - const char *err = kernelize_one(&reti, &outputs, stream, sh, sinks); + const char *err = kernelize_one(&reti, &outputs, stream, sh, sinks, &payload_types); if (err) ilog(LOG_WARNING, "No support for kernel packet forwarding available (%s)", err); } } + g_list_free(payload_types); + if (!reti.local.family) goto no_kernel;