From 0914bf761de0c0970108b1846689904d907d2c15 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Sat, 11 Mar 2023 10:52:32 -0500 Subject: [PATCH] MT#55283 add per-call dtmf-log-dest Closes #1628 Change-Id: If2a4175cc64e1143de8c749676ed215f7dc52915 --- daemon/call_interfaces.c | 10 ++++++++++ daemon/dtmf.c | 19 ++++++++++++++----- daemon/media_socket.c | 2 +- docs/ng_control_protocol.md | 8 ++++++++ include/call.h | 1 + include/call_interfaces.h | 1 + include/dtmf.h | 2 +- 7 files changed, 36 insertions(+), 7 deletions(-) diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index bcf98fd75..c9e2b2b75 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1653,6 +1653,14 @@ static void call_ng_main_flags(struct sdp_ng_flags *out, str *key, bencode_item_ ilog(LOG_WARN, "Failed to parse 'xmlrpc-callback' address '" STR_FORMAT "'", STR_FMT(&s)); break; + case CSH_LOOKUP("dtmf-log-dest"): + case CSH_LOOKUP("DTMF-log-dest"): + case CSH_LOOKUP("dtmf-log-destination"): + case CSH_LOOKUP("DTMF-log-destination"): + if (endpoint_parse_any_str(&out->dtmf_log_dest, &s)) + ilog(LOG_WARN, "Failed to parse 'dtmf-log-dest' address '" STR_FORMAT "'", + STR_FMT(&s)); + break; case CSH_LOOKUP("codec"): call_ng_dict_iter(out, value, call_ng_codec_flags); break; @@ -2123,6 +2131,8 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t if (flags.xmlrpc_callback.family) call->xmlrpc_callback = flags.xmlrpc_callback; + if (flags.dtmf_log_dest.address.family) + call->dtmf_log_dest = flags.dtmf_log_dest; /* At least the random ICE strings are contained within the call struct, so we * need to hold a ref until we're done sending the reply */ diff --git a/daemon/dtmf.c b/daemon/dtmf.c index f5f8b8149..3fa40c0d4 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -118,13 +118,15 @@ static GString *dtmf_json_print(struct call_media *media, unsigned int event, un return buf; } -bool dtmf_do_logging(bool injected) { +bool dtmf_do_logging(const struct call *c, bool injected) { if (injected && rtpe_config.dtmf_no_log_injects) return false; if (_log_facility_dtmf) return true; if (rtpe_config.dtmf_udp_ep.port) return true; + if (c->dtmf_log_dest.address.family) + return true; if (rtpe_config.dtmf_via_ng) return true; return false; @@ -146,17 +148,24 @@ static void dtmf_end_event(struct call_media *media, unsigned int event, unsigne .volume = 0, .block_dtmf = media->monologue->block_dtmf }; g_queue_push_tail(&media->dtmf_send, ev); - if (!dtmf_do_logging(injected)) + if (!dtmf_do_logging(media->call, injected)) return; GString *buf = dtmf_json_print(media, event, volume, duration, fsin, clockrate); if (_log_facility_dtmf) dtmflog(buf); - if (rtpe_config.dtmf_udp_ep.port) - if (socket_sendto(&dtmf_log_sock, buf->str, buf->len, &rtpe_config.dtmf_udp_ep) < 0) + + const endpoint_t *udp_dst = NULL; + if (media->call->dtmf_log_dest.address.family) + udp_dst = &media->call->dtmf_log_dest; + else if (rtpe_config.dtmf_udp_ep.address.family) + udp_dst = &rtpe_config.dtmf_udp_ep; + + if (udp_dst) + if (socket_sendto(&dtmf_log_sock, buf->str, buf->len, udp_dst)) ilog(LOG_ERR, "Error sending DTMF event info to UDP destination %s: %s", - endpoint_print_buf(&rtpe_config.dtmf_udp_ep), + endpoint_print_buf(udp_dst), strerror(errno)); if (rtpe_config.dtmf_via_ng) diff --git a/daemon/media_socket.c b/daemon/media_socket.c index a3088a9ce..a057b3ba1 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1703,7 +1703,7 @@ static const struct streamhandler *__determine_handler(struct packet_stream *in, if (!sh) must_recrypt = true; - else if (dtmf_do_logging(false)) + else if (dtmf_do_logging(in->call, false)) must_recrypt = true; else if (MEDIA_ISSET(in->media, DTLS) || (out && MEDIA_ISSET(out->media, DTLS))) must_recrypt = true; diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index 2da9172fe..3afcb4b65 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -255,6 +255,14 @@ Optionally included keys are: reproduced after the given delay. DTMF blocking modes are honoured at the time when the DTMF events are reproduced. +* `DTMF-log-dest` + + Contains a destination address and port for the DTMF logging feature. This + overrides the global destination from the `dtmf-log-dest` config option on + a per-call basis. Even if the global config option is unset, setting the + destination address/port via this option enables DTMF logging for this + call. + * `endpoint-learning` Contains one of the strings `off`, `immediate`, `delayed` or `heuristic`. This tells rtpengine which endpoint learning algorithm to use and overrides the `endpoint-learning` configuration option. This option can also be put into the `flags` list using a prefix of `endpoint-learning-`. diff --git a/include/call.h b/include/call.h index 3e02c3f12..286ef5802 100644 --- a/include/call.h +++ b/include/call.h @@ -657,6 +657,7 @@ struct call { char *created_from; sockaddr_t created_from_addr; sockaddr_t xmlrpc_callback; + endpoint_t dtmf_log_dest; unsigned int redis_hosted_db; diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 0e9beeb4e..b24a6c402 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -42,6 +42,7 @@ struct sdp_ng_flags { str to_label; str address; sockaddr_t xmlrpc_callback; + endpoint_t dtmf_log_dest; GQueue codec_strip; GHashTable *codec_except; GQueue codec_offer; diff --git a/include/dtmf.h b/include/dtmf.h index 96c72957a..d63f42476 100644 --- a/include/dtmf.h +++ b/include/dtmf.h @@ -33,7 +33,7 @@ int dtmf_code_from_char(char); char dtmf_code_to_char(int code); const char *dtmf_inject(struct call_media *media, int code, int volume, int duration, int pause, struct call_media *sink); -bool dtmf_do_logging(bool injected); +bool dtmf_do_logging(const struct call *, bool injected); void dtmf_dsp_event(const struct dtmf_event *new_event, struct dtmf_event *cur_event, struct call_media *media, int clockrate, uint64_t ts, bool injected); enum block_dtmf_mode dtmf_get_block_mode(struct call *call, struct call_monologue *ml);