diff --git a/daemon/codec.c b/daemon/codec.c index 4b95614e6..2d86ad4a3 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -297,6 +297,7 @@ static codec_handler_func handler_func_playback; static codec_handler_func handler_func_inject_dtmf; static codec_handler_func handler_func_dtmf; static codec_handler_func handler_func_t38; +static codec_handler_func handler_func_blackhole; static struct ssrc_entry *__ssrc_handler_transcode_new(void *p); static struct ssrc_entry *__ssrc_handler_decode_new(void *p); @@ -347,6 +348,14 @@ static struct codec_handler codec_handler_stub_ssrc = { .kernelize = true, .passthrough = true, }; +static struct codec_handler codec_handler_stub_blackhole = { + .source_pt.payload_type = -1, + .dest_pt.payload_type = -1, + .handler_func = handler_func_blackhole, + .blackhole = true, + .kernelize = true, + .passthrough = false, +}; @@ -369,6 +378,7 @@ static void __handler_shutdown(struct codec_handler *handler) { handler->pcm_dtmf_detect = false; handler->passthrough = false; handler->payload_len = 0; + handler->blackhole = false; codec_handler_free(&handler->dtmf_injector); @@ -485,6 +495,10 @@ static void __handler_stats_entry(struct codec_handler *handler) { __atomic_fetch_add(&stats_entry->num_transcoders, 1, __ATOMIC_RELAXED); } +static int handler_func_blackhole(struct codec_handler *h, struct media_packet *mp) { + return 0; +} + static void __reset_sequencer(void *p, void *dummy) { struct ssrc_entry_call *s = p; if (s->sequencers) @@ -506,7 +520,7 @@ static bool __make_transcoder_full(struct codec_handler *handler, rtp_payload_ty goto reset; if (!rtp_payload_type_eq_exact(dest, &handler->dest_pt)) goto reset; - if (handler->handler_func != handler_func_transcode) + if (handler->handler_func != handler_func_transcode && handler->handler_func != handler_func_blackhole) goto reset; if (handler->packet_decoded != packet_decoded) goto reset; @@ -1780,6 +1794,8 @@ struct codec_handler *codec_handler_get(struct call_media *m, int payload_type, out: if (ret) return ret; + if (MEDIA_ISSET(sink, SELECT_PT)) + return &codec_handler_stub_blackhole; if (sh && sh->attrs.transcoding) return &codec_handler_stub_ssrc; #endif diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 86d4061f1..0f362bec5 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1657,6 +1657,8 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st struct codec_handler *ch = codec_handler_get(media, rs->payload_type, ksink->media, ksh); + if (ch->blackhole) + s->manipulate_pt = true; if (ch->kernelize) continue; @@ -1744,6 +1746,8 @@ static const char *kernelize_one(kernelize_state *s, if (ML_ISSET(media->monologue, BLOCK_SHORT) && ch->payload_len) rpt->min_payload_len = ch->payload_len; + + rpt->blackhole = ch->blackhole; } } diff --git a/include/call.h b/include/call.h index 83539dea2..a010e37e9 100644 --- a/include/call.h +++ b/include/call.h @@ -218,6 +218,7 @@ enum { * if not set, then inactive. */ #define MEDIA_FLAG_REAL_SENDONLY (1LL << 35) +#define MEDIA_FLAG_SELECT_PT (1LL << 36) /* struct call_monologue */ #define ML_FLAG_REC_FORWARDING (1LL << 16) diff --git a/include/codec.h b/include/codec.h index 28e212c20..c33b7a18c 100644 --- a/include/codec.h +++ b/include/codec.h @@ -58,6 +58,7 @@ struct codec_handler { bool kernelize:1; bool transcoder:1; bool pcm_dtmf_detect:1; + bool blackhole:1; size_t payload_len; // for short-packet blocking diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index e5b6a574c..da749e79e 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -1796,6 +1796,9 @@ static int proc_list_show(struct seq_file *f, void *v) { g->target.pt_stats[j]->payload_type, o->output.pt_output[j].replace_pattern_len, o->output.pt_output[j].min_payload_len); + if (o->output.pt_output[j].blackhole) + seq_printf(f, " RTP payload type %3u: blackhole\n", + g->target.pt_stats[j]->payload_type); } proc_list_crypto_print(f, &o->encrypt_rtp, &o->output.encrypt, "encryption"); @@ -6023,8 +6026,12 @@ static bool proxy_packet_output_rtXp(struct sk_buff *skb, struct rtpengine_outpu return true; } - // pattern rewriting if (rtp_pt_idx >= 0) { + // blackhole? + if (o->output.pt_output[rtp_pt_idx].blackhole) + return false; + + // pattern rewriting if (o->output.pt_output[rtp_pt_idx].min_payload_len && rtp->payload_len < o->output.pt_output[rtp_pt_idx].min_payload_len) return false; diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index bb6264e20..738ee426c 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -78,6 +78,7 @@ struct rtpengine_pt_output { unsigned int min_payload_len; char replace_pattern[16]; unsigned char replace_pattern_len; + unsigned int blackhole:1; }; struct rtpengine_target_info {