TT#43556 support blocking of DTMF event packets

Change-Id: I7ef43ddb254b1583c2dc69b44a13b978eff15510
changes/93/23193/5
Richard Fuchs 7 years ago
parent 4edfe6537e
commit e67b9c40da

@ -1056,6 +1056,8 @@ a string and determines the type of message. Currently the following commands ar
* query
* start recording
* stop recording
* block DTMF
* unblock DTMF
The response dictionary must contain at least one key called `result`. The value can be either `ok` or `error`.
For the `ping` command, the additional value `pong` is allowed. If the result is `error`, then another key
@ -1893,3 +1895,12 @@ The `stop recording` message must contain the key `call-id` as defined above. Th
no additional keys.
Disables call recording for the call. This can be sent during a call to imediatley stop recording it.
`block DTMF` and `unblock DTMF` Messages
----------------------------------------
These message types must include the key `call-id` in the message. They enable and disable blocking of DTMF
events (RFC 4733 type packets) for a call, respectively.
When DTMF blocking is enabled for a call, DTMF event packets will not be forwarded to the receiving peer.
If DTMF logging is enabled, DTMF events will still be logged to syslog while blocking is enabled. Blocking
of DTMF events happens for an entire call and can be enabled and disabled at any time during call runtime.

@ -1355,6 +1355,45 @@ const char *call_stop_recording_ng(bencode_item_t *input, bencode_item_t *output
return NULL;
}
const char *call_block_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
str callid;
struct call *call;
if (!bencode_dictionary_get_str(input, "call-id", &callid))
return "No call-id in message";
call = call_get_opmode(&callid, OP_OTHER);
if (!call)
return "Unknown call-id";
ilog(LOG_INFO, "Blocking DTMF");
call->block_dtmf = 1;
rwlock_unlock_w(&call->master_lock);
obj_put(call);
return NULL;
}
const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
str callid;
struct call *call;
if (!bencode_dictionary_get_str(input, "call-id", &callid))
return "No call-id in message";
call = call_get_opmode(&callid, OP_OTHER);
if (!call)
return "Unknown call-id";
ilog(LOG_INFO, "Unblocking DTMF");
call->block_dtmf = 0;
rwlock_unlock_w(&call->master_lock);
obj_put(call);
return NULL;
}
int call_interfaces_init() {
const char *errptr;
int erroff;

@ -461,8 +461,8 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer)
streambuf_printf(replybuffer, "\n\n");
streambuf_printf(replybuffer, "Control statistics:\n\n");
streambuf_printf(replybuffer, " %20s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s \n",
"Proxy", "Offer", "Answer", "Delete", "Ping", "List", "Query", "StartRec", "StopRec", "Errors");
streambuf_printf(replybuffer, " %20s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s \n",
"Proxy", "Offer", "Answer", "Delete", "Ping", "List", "Query", "StartRec", "StopRec", "Errors", "BlkDTMF", "UnblkDTMF");
mutex_lock(&rtpe_cngs_lock);
GList *list = g_hash_table_get_values(rtpe_cngs_hash);
@ -472,7 +472,7 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer)
}
for (GList *l = list; l; l = l->next) {
struct control_ng_stats* cur = l->data;
streambuf_printf(replybuffer, " %20s | %10u | %10u | %10u | %10u | %10u | %10u | %10u | %10u | %10u \n",
streambuf_printf(replybuffer, " %20s | %10u | %10u | %10u | %10u | %10u | %10u | %10u | %10u | %10u | %10u | %10u \n",
sockaddr_print_buf(&cur->proxy),
cur->offer,
cur->answer,
@ -482,7 +482,9 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer)
cur->query,
cur->start_recording,
cur->stop_recording,
cur->errors);
cur->errors,
cur->block_dtmf,
cur->unblock_dtmf);
}
streambuf_printf(replybuffer, "\n\n");
mutex_unlock(&rtpe_cngs_lock);

@ -647,13 +647,15 @@ static int packet_dtmf(struct codec_ssrc_handler *ch, struct transcode_packet *p
}
}
packet_dtmf_fwd(ch, packet, mp, 1);
if (!mp->call->block_dtmf)
packet_dtmf_fwd(ch, packet, mp, 1);
return 0;
}
static void packet_dtmf_dup(struct codec_ssrc_handler *ch, struct transcode_packet *packet,
struct media_packet *mp)
{
packet_dtmf_fwd(ch, packet, mp, 0);
if (!mp->call->block_dtmf)
packet_dtmf_fwd(ch, packet, mp, 0);
}
static int handler_func_dtmf(struct codec_handler *h, struct media_packet *mp) {

@ -216,6 +216,14 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin
errstr = call_stop_recording_ng(dict, resp);
g_atomic_int_inc(&cur->stop_recording);
}
else if (!str_cmp(&cmd, "block DTMF")) {
errstr = call_block_dtmf_ng(dict, resp);
g_atomic_int_inc(&cur->block_dtmf);
}
else if (!str_cmp(&cmd, "unblock DTMF")) {
errstr = call_unblock_dtmf_ng(dict, resp);
g_atomic_int_inc(&cur->unblock_dtmf);
}
else
{
errstr = "Unrecognized command";

@ -1579,6 +1579,8 @@ static void json_restore_call(struct redis *r, const str *callid, enum call_type
c->created_from = call_strdup(c, id.s);
if (!redis_hash_get_str(&id, &call, "created_from_addr"))
sockaddr_parse_any_str(&c->created_from_addr, &id);
if (!redis_hash_get_int(&i, &call, "block_dtmf"))
c->block_dtmf = i ? 1 : 0;
err = "missing 'redis_hosted_db' value";
if (redis_hash_get_unsigned((unsigned int *) &c->redis_hosted_db, &call, "redis_hosted_db"))
@ -1859,6 +1861,7 @@ char* redis_encode_json(struct call *c) {
JSON_SET_SIMPLE_CSTR("created_from_addr",sockaddr_print_buf(&c->created_from_addr));
JSON_SET_SIMPLE("redis_hosted_db","%u",c->redis_hosted_db);
JSON_SET_SIMPLE_STR("recording_metadata",&c->metadata);
JSON_SET_SIMPLE("block_dtmf","%i",c->block_dtmf ? 1 : 0);
if ((rec = c->recording)) {
JSON_SET_SIMPLE_CSTR("recording_meta_prefix",rec->meta_prefix);

@ -399,6 +399,8 @@ struct call {
struct recording *recording;
str metadata;
int block_dtmf:1;
};

@ -94,6 +94,8 @@ const char *call_query_ng(bencode_item_t *, bencode_item_t *);
const char *call_list_ng(bencode_item_t *, bencode_item_t *);
const char *call_start_recording_ng(bencode_item_t *, bencode_item_t *);
const char *call_stop_recording_ng(bencode_item_t *, bencode_item_t *);
const char *call_block_dtmf_ng(bencode_item_t *, bencode_item_t *);
const char *call_unblock_dtmf_ng(bencode_item_t *, bencode_item_t *);
void ng_call_stats(struct call *call, const str *fromtag, const str *totag, bencode_item_t *output,
struct call_stats *totals);

@ -19,6 +19,8 @@ struct control_ng_stats {
int list;
int start_recording;
int stop_recording;
int block_dtmf;
int unblock_dtmf;
int errors;
};

@ -806,5 +806,168 @@ int main() {
packet_seq_exp(A, 0, PCMU_payload, 1000960, 212, 0, PCMU_payload, 5); // expected seq is 207+5 for PT 8
end();
// plain DTMF passthrough w/o transcoding - blocking
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
offer();
expect(A, recv, "");
expect(A, send, "8/PCMA/8000 101/telephone-event/8000");
expect(B, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(B, send, "");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(A, send, "8/PCMA/8000 101/telephone-event/8000");
expect(B, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(B, send, "8/PCMA/8000 101/telephone-event/8000");
packet_seq(A, 8, PCMA_payload, 1000000, 200, 8, PCMA_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"(null)\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq_exp(A, 8, PCMA_payload, 1000960, 206, 8, PCMA_payload, 6); // expected seq is 200+6 for PT 8
packet_seq(A, 8, PCMA_payload, 1001120, 207, 8, PCMA_payload);
// enable blocking
call.block_dtmf = 1;
// start with marker
packet_seq_exp(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, -1, "", 0);
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, -1, "");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, -1, "");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"(null)\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
dtmf("");
// final audio RTP test
packet_seq_exp(A, 8, PCMA_payload, 1000960, 212, 8, PCMA_payload, 5); // expected seq is 207+5 for PT 8
end();
// DTMF passthrough w/ transcoding - blocking
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
transcode(PCMU);
offer();
expect(A, recv, "");
expect(A, send, "8/PCMA/8000 101/telephone-event/8000");
expect(B, recv, "8/PCMA/8000 101/telephone-event/8000 0/PCMU/8000");
expect(B, send, "");
sdp_pt(0, PCMU, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(A, send, "8/PCMA/8000 101/telephone-event/8000");
expect(B, recv, "101/telephone-event/8000 0/PCMU/8000");
expect(B, send, "0/PCMU/8000 101/telephone-event/8000");
packet_seq(A, 8, PCMA_payload, 1000000, 200, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"(null)\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq_exp(A, 8, PCMA_payload, 1000960, 206, 0, PCMU_payload, 6); // expected seq is 200+6 for PT 8
packet_seq(A, 8, PCMA_payload, 1001120, 207, 0, PCMU_payload);
// enable blocking
call.block_dtmf = 1;
// start with marker
packet_seq_exp(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, -1, "", 0);
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, -1, "");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, -1, "");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"(null)\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
dtmf("");
// final audio RTP test
packet_seq_exp(A, 8, PCMA_payload, 1000960, 212, 0, PCMU_payload, 1); // expected seq is 207+1 for PT 8
end();
// plain DTMF passthrough w/o transcoding w/ implicit primary payload type - blocking
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
offer();
expect(A, recv, "");
expect(A, send, "8/PCMA/8000 101/telephone-event/8000");
expect(B, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(B, send, "");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(A, send, "8/PCMA/8000 101/telephone-event/8000");
expect(B, recv, "8/PCMA/8000 101/telephone-event/8000");
expect(B, send, "8/PCMA/8000 101/telephone-event/8000");
packet_seq(A, 0, PCMU_payload, 1000000, 200, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"(null)\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq_exp(A, 0, PCMU_payload, 1000960, 206, 0, PCMU_payload, 6); // expected seq is 200+6 for PT 8
packet_seq(A, 0, PCMU_payload, 1001120, 207, 0, PCMU_payload);
// enable blocking
call.block_dtmf = 1;
// start with marker
packet_seq_exp(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, -1, "", 0);
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, -1, "");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, -1, "");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"(null)\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
dtmf("");
// final audio RTP test
packet_seq_exp(A, 0, PCMU_payload, 1000960, 212, 0, PCMU_payload, 5); // expected seq is 207+5 for PT 8
end();
return 0;
}

Loading…
Cancel
Save