diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 455c06c39..2c5c93be0 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1442,6 +1442,7 @@ void call_ng_flags_init(sdp_ng_flags *out, enum ng_opmode opmode) { out->frequencies = g_array_new(false, false, sizeof(int)); for (int i = 0; i < __MT_MAX; ++i) out->sdp_media_remove[i] = false; + out->t38_version = -1; } static void call_ng_direction_flag_iter(str *s, unsigned int i, helper_arg arg) { @@ -2105,6 +2106,17 @@ void call_ng_main_flags(const ng_parser_t *parser, str *key, parser_arg value, h case CSH_LOOKUP("t.38"): call_ng_flags_str_list(parser, value, ng_t38_option, out); break; + + case CSH_LOOKUP("T38-version"): + case CSH_LOOKUP("T.38-version"): + case CSH_LOOKUP("t38-version"): + case CSH_LOOKUP("t.38-version"): + case CSH_LOOKUP("T38 version"): + case CSH_LOOKUP("T.38 version"): + case CSH_LOOKUP("t38 version"): + case CSH_LOOKUP("t.38 version"): + out->t38_version = parser->get_int_str(value, out->t38_version); + break; #endif case CSH_LOOKUP("template"):; str *tplate = t_hash_table_lookup(rtpe_signalling_templates, &s); diff --git a/daemon/codec.c b/daemon/codec.c index ce4853c2a..4ff9063da 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -876,6 +876,10 @@ static void __t38_options_from_flags(struct t38_options *t_opts, const sdp_ng_fl t38_opt(no_v29); t38_opt(no_v34); t38_opt(no_iaf); +#undef t38_opt + + if (flags && flags->t38_version >= 0) + t_opts->version = flags->t38_version; } static void __check_t38_gateway(struct call_media *pcm_media, struct call_media *t38_media, @@ -891,6 +895,7 @@ static void __check_t38_gateway(struct call_media *pcm_media, struct call_media t_opts.fec_span = 3; t_opts.max_ec_entries = 3; } + __t38_options_from_flags(&t_opts, flags); MEDIA_SET(pcm_media, GENERATOR); diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index 66ea3f4c2..868b814c9 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -860,6 +860,14 @@ Optionally included keys are: Use UDPTL FEC instead of redundancy. Only useful with `T.38=force` as it's a negotiated parameter. +* `T.38 version` + + Sets the T.38 version number to use for the T.38 gateway. The default is + version zero, or to go along with what has been advertised in the SDP if + responding to a received T.38 offer. Overriding the version to zero + regardless of what has been advertised in the SDP can solve T.38 gateway + problems against certain endpoints. + * `volume` Sets the tone volume for `DTMF-security` modes `tone`, `zero, `DTMF`, diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 6b614cbe2..6063e45b3 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -154,6 +154,7 @@ struct sdp_ng_flags { str vsc_pause_rec; str vsc_pause_resume_rec; str vsc_start_pause_resume_rec; + int t38_version; #define X(x) str_q x; RTPE_NG_FLAGS_STR_Q_PARAMS diff --git a/t/auto-daemon-tests-t38.pl b/t/auto-daemon-tests-t38.pl index a740d6f4b..cd3bdf784 100755 --- a/t/auto-daemon-tests-t38.pl +++ b/t/auto-daemon-tests-t38.pl @@ -681,6 +681,114 @@ t38_gw_test('FEC span 5', +new_call; + +offer('override T.38 version control', { 'T.38' => [ 'decode' ] }, <<SDP); +v=0 +o=- 1545997027 1 IN IP4 198.51.100.1 +s=tester +t=0 0 +m=image 4000 udptl t38 +c=IN IP4 198.51.100.1 +a=sendrecv +a=T38FaxVersion:1 +a=T38MaxBitRate:14400 +a=T38FaxRateManagement:transferredTCF +a=T38FaxMaxBuffer:262 +a=T38FaxMaxDatagram:300 +a=T38FaxUdpEC:t38UDPRedundancy +---------------------------------- +v=0 +o=- 1545997027 1 IN IP4 198.51.100.1 +s=tester +t=0 0 +m=audio PORT RTP/AVP 0 8 +c=IN IP4 203.0.113.1 +a=rtpmap:0 PCMU/8000 +a=rtpmap:8 PCMA/8000 +a=sendrecv +a=rtcp:PORT +SDP + +answer('override T.38 version control', { }, <<SDP); +v=0 +o=- 1545997027 1 IN IP4 198.51.100.3 +s=tester +t=0 0 +m=audio 4002 RTP/AVP 8 +c=IN IP4 198.51.100.3 +a=sendrecv +-------------------------------------- +v=0 +o=- 1545997027 1 IN IP4 198.51.100.3 +s=tester +t=0 0 +m=image PORT udptl t38 +c=IN IP4 203.0.113.1 +a=T38FaxVersion:1 +a=T38MaxBitRate:14400 +a=T38FaxRateManagement:transferredTCF +a=T38FaxMaxBuffer:1800 +a=T38FaxMaxDatagram:512 +a=T38FaxUdpEC:t38UDPRedundancy +a=sendrecv +SDP + + +new_call; + +offer('override T.38 version', { 'T.38' => [ 'decode' ], 'T.38 version' => 0 }, <<SDP); +v=0 +o=- 1545997027 1 IN IP4 198.51.100.1 +s=tester +t=0 0 +m=image 4000 udptl t38 +c=IN IP4 198.51.100.1 +a=sendrecv +a=T38FaxVersion:1 +a=T38MaxBitRate:14400 +a=T38FaxRateManagement:transferredTCF +a=T38FaxMaxBuffer:262 +a=T38FaxMaxDatagram:300 +a=T38FaxUdpEC:t38UDPRedundancy +---------------------------------- +v=0 +o=- 1545997027 1 IN IP4 198.51.100.1 +s=tester +t=0 0 +m=audio PORT RTP/AVP 0 8 +c=IN IP4 203.0.113.1 +a=rtpmap:0 PCMU/8000 +a=rtpmap:8 PCMA/8000 +a=sendrecv +a=rtcp:PORT +SDP + +answer('override T.38 version', { }, <<SDP); +v=0 +o=- 1545997027 1 IN IP4 198.51.100.3 +s=tester +t=0 0 +m=audio 4002 RTP/AVP 8 +c=IN IP4 198.51.100.3 +a=sendrecv +-------------------------------------- +v=0 +o=- 1545997027 1 IN IP4 198.51.100.3 +s=tester +t=0 0 +m=image PORT udptl t38 +c=IN IP4 203.0.113.1 +a=T38FaxVersion:0 +a=T38MaxBitRate:14400 +a=T38FaxRateManagement:transferredTCF +a=T38FaxMaxBuffer:1800 +a=T38FaxMaxDatagram:512 +a=T38FaxUdpEC:t38UDPRedundancy +a=sendrecv +SDP + + # XXX packet loss tests # XXX tests of different SDP options