diff --git a/daemon/codec.c b/daemon/codec.c index 574ea267b..383c81c9c 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -2251,6 +2251,8 @@ void codec_packet_free(void *pp) { struct codec_packet *p = pp; if (p->free_func) p->free_func(p->s.s); + if (p->plain_free_func && p->plain.s) + p->plain_free_func(p->plain.s); ssrc_ctx_put(&p->ssrc_out); g_slice_free1(sizeof(*p), p); } diff --git a/daemon/main.c b/daemon/main.c index b3192a180..542f01815 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -516,6 +516,7 @@ static void options(int *argc, char ***argv) { { "recording-dir", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.spooldir, "Directory for storing pcap and metadata files", "FILE" }, { "recording-method",0, 0, G_OPTION_ARG_STRING, &rtpe_config.rec_method, "Strategy for call recording", "pcap|proc|all" }, { "recording-format",0, 0, G_OPTION_ARG_STRING, &rtpe_config.rec_format, "File format for stored pcap files", "raw|eth" }, + { "record-egress",0, 0, G_OPTION_ARG_NONE, &rtpe_config.rec_egress, "Recording egress media instead of ingress", NULL }, #ifdef WITH_IPTABLES_OPTION { "iptables-chain",0,0, G_OPTION_ARG_STRING, &rtpe_config.iptables_chain,"Add explicit firewall rules to this iptables chain","STRING" }, #endif diff --git a/daemon/media_player.c b/daemon/media_player.c index 3348f340e..c9869a136 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -252,6 +252,17 @@ static bool __send_timer_send_1(struct rtp_header *rh, struct packet_stream *sin socket_sendto(&sink_fd->socket, cp->s.s, cp->s.len, &sink->endpoint); + if (sink->call->recording && rtpe_config.rec_egress) { + // fill in required members + struct media_packet mp = { + .call = sink->call, + .stream = sink, + .sfd = sink_fd, + .fsin = sink->endpoint, + }; + dump_packet(&mp, cp->plain.s ? &cp->plain : &cp->s); + } + atomic64_inc(&sink->stats_out.packets); atomic64_add(&sink->stats_out.bytes, cp->s.len); atomic64_inc(&sink_fd->local_intf->stats.out.packets); diff --git a/daemon/media_socket.c b/daemon/media_socket.c index f4ea00799..0546f00a6 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -2043,6 +2043,10 @@ int media_packet_encrypt(rewrite_func encrypt_func, struct packet_stream *out, s for (GList *l = mp->packets_out.head; l; l = l->next) { struct codec_packet *p = l->data; + if (mp->call->recording && rtpe_config.rec_egress) { + str_init_dup_str(&p->plain, &p->s); + p->plain_free_func = free; + } int encret = encrypt_func(&p->s, out, mp->ssrc_out); if (encret == 1) ret |= 0x02; @@ -2501,7 +2505,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { rtp_padding(phc->mp.rtp, &phc->mp.payload); // If recording pcap dumper is set, then we record the call. - if (phc->mp.call->recording) + if (phc->mp.call->recording && !rtpe_config.rec_egress) dump_packet(&phc->mp, &phc->s); phc->mp.raw = phc->s; diff --git a/daemon/rtpengine.pod b/daemon/rtpengine.pod index 3c576b82a..6e8adc8c6 100644 --- a/daemon/rtpengine.pod +++ b/daemon/rtpengine.pod @@ -649,6 +649,13 @@ ethernet header. When set to B, a fake ethernet header is added, making each package 14 bytes larger. +=item B<--record-egress> + +Apply media recording to egress media streams (as they are sent by +B) instead of media streams as they are received. This makes it +possible to include manipulated and generated media (such as from the B command) in the recordings. + =item B<--iptables-chain=>I This option enables explicit management of an iptables chain. diff --git a/include/codec.h b/include/codec.h index 361860e98..39de5b670 100644 --- a/include/codec.h +++ b/include/codec.h @@ -69,11 +69,13 @@ struct codec_handler { struct codec_packet { struct timerthread_queue_entry ttq_entry; str s; + str plain; struct rtp_header *rtp; unsigned long ts; unsigned int clockrate; struct ssrc_ctx *ssrc_out; void (*free_func)(void *); + void (*plain_free_func)(void *); }; struct codec_scheduler { diff --git a/include/main.h b/include/main.h index e836f91c9..900b43c7d 100644 --- a/include/main.h +++ b/include/main.h @@ -84,6 +84,7 @@ struct rtpengine_config { char *spooldir; char *rec_method; char *rec_format; + int rec_egress; char *iptables_chain; int load_limit; int cpu_limit;