Skip to content

core,app_dial,pjsip: Implement Advanced Codec Negotiation (ACN) - #285

Draft
maximilianfridrich wants to merge 2 commits into
asterisk:masterfrom
maximilianfridrich:master-issue-223
Draft

maximilianfridrich wants to merge 2 commits into
asterisk:masterfrom
maximilianfridrich:master-issue-223

Conversation

@maximilianfridrich

Copy link
Copy Markdown
Contributor

Advanced Codec Negotiation is now implemented for the dial application, pjsip channels and local channels.

Resolves: #223

UpgradeNote: The two pjsip.conf options "incoming_call_offer_pref" and "outgoing_call_offer_pref" have been removed. Instead, the new options "codec_prefs_incoming_answer", "codec_prefs_incoming_offer", "codec_prefs_outgoing_answer", "codec_prefs_outgoing_offer" must be used. Even if the old settings were not used, this could break existing deployments as the default ACN options are now in use and they might behave differently in some call flows (e.g. by default, pending codecs are always preferred, not the endpoint configuration).

UserNote: The Advanced Codec Negotiation feature is now implemented.

@maximilianfridrich

maximilianfridrich commented Aug 30, 2023

Copy link
Copy Markdown
Contributor Author

testsuite-test-pr: 20
cherry-pick-to: none

@jcolp

jcolp commented Aug 30, 2023

Copy link
Copy Markdown
Member

I haven't looked at the code, just the upgrade note, but the options can not be removed. They must continue to exist.

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

This PR must be tested with the corresponding testsuite PR which adds 48 tests to test the codec negotiation:

Further, 10 tests were adopted to reflect the new behavior. For those tests, pjsip.conf had to be adopted to use the new ACN settings. The default settings prefer the pending stream while these tests expect the configured settings to be preferred.

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

the options can not be removed. They must continue to exist.

@jcolp And they must continue to work? Or silently be ignored like the ACN settings were? I'm not sure if I see a way for both settings to co-exist without interfering with each other.

@jcolp

jcolp commented Aug 30, 2023

Copy link
Copy Markdown
Member

Yes. We can not remove options in minor versions, or alter their behavior, unless there is a critical reason why - such as a security issue. This does not rise to that level.

@jcolp

jcolp commented Aug 30, 2023

Copy link
Copy Markdown
Member

For example, if the options are kept but default to empty in the code we can determine that they are actually unset. Default behavior should remain the same in that case even if the options were removed. If they are set then those settings take priority. If unset then the other options take priority.

  1. Default behavior with this change should match previous versions
  2. If the incoming_* and outgoing_* options are set by the user, then they take priority

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

We can not remove options in minor versions, or alter their behavior

Makes sense, I probably should have checked with the maintainers first. So would it be an option for Asterisk 21?

@jcolp

jcolp commented Aug 30, 2023

Copy link
Copy Markdown
Member

Asterisk 21, once branched, can no longer receive breaking changes.

@jcolp

jcolp commented Aug 30, 2023

Copy link
Copy Markdown
Member

I'm sticking to the policy that breaking changes are for standard releases, which next would be 23. If this change can be altered to maintain backwards compatibility then it would be eligible for all.

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

Ok, then I will look into your suggestion and try to find a way to not change the existing behavior and not remove any settings.

Is it possible to mark this PR as a draft while I do that?

@jcolp
jcolp marked this pull request as draft August 30, 2023 09:58
@jcolp

jcolp commented Aug 30, 2023

Copy link
Copy Markdown
Member

I've converted it to a draft.

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author
  1. Default behavior with this change should match previous versions
  2. If the incoming_* and outgoing_* options are set by the user, then they take priority

Consider the case where neither the "old" options incoming_call_offer_pref and outgoing_call_offer_pref nor the "new" codec_prefs_* options are set. As you described it, since the old options are unset, the new settings are used. And in order to not change the default behavior, I must change the defaults of two of the new ACN options:

codec_prefs_incoming_offer = prefer: configured, operation: intersect, keep: all, transcode: allow
codec_prefs_incoming_answer = prefer: configured, operation: intersect, keep: all, transcode: allow

They must be set to prefer: configured, this is the only way the requirements can be met. So far, the documentation (and code) had prefer: pending as default. The ACN settings had no effect so far, so I think this should be alright.

@gtjoseph

Copy link
Copy Markdown
Member

Thanks for picking this up!!!
I'm going to try and set some time aside to review in detail.

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

@gtjoseph Thank you! I am now incorporating Joshua's remarks and I noticed that some fax/pjsip tests failed (which I didn't check). So this is still a WIP, but we have confirmed that the ACN is working as expected (e.g. see the linked testsuite PR and we have done manual testing as well).

@maximilianfridrich

maximilianfridrich commented Aug 30, 2023

Copy link
Copy Markdown
Contributor Author

If the incoming_* and outgoing_* options are set by the user, then they take priority.

To be more precise, I think the logic should be:

As soon as one of incoming_call_offer_pref or outgoing_call_offer_pref is set, the ACN options are ignored.

I think everything else would lead to maximum confusion. I will state this in the docs for the settings.

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

Update: We can not really invest more time into making this patch also work with the old settings.

@jcolp Is the removal of the incoming_call_offer_pref and outgoing_call_offer_pref an option for the next Asterisk major version release? If so, how can we go about this? Should we close this PR and re-open it at a better time?

We are confident that this patch implements ACN as it is supposed to, the only missing piece seems to be the failing fax tests.

@InterLinked1

Copy link
Copy Markdown
Contributor

@jcolp Is the removal of the incoming_call_offer_pref and outgoing_call_offer_pref an option for the next Asterisk major version release? If so, how can we go about this? Should we close this PR and re-open it at a better time?

There is a waiting-for-standard-release-development-cycle label for this purpose, that could be applied. But I'm not sure contributors can add it themselves.

@jcolp jcolp added the waiting-for-standard-release-development-cycle This change is pending the master branch being the next standard release development cycle. label Aug 31, 2023
@jcolp

jcolp commented Aug 31, 2023

Copy link
Copy Markdown
Member

I've added it.

@gtjoseph
gtjoseph force-pushed the master branch 4 times, most recently from c6b7d4b to 31abe63 Compare September 5, 2023 19:25
@maximilianfridrich

maximilianfridrich commented Jan 10, 2025

Copy link
Copy Markdown
Contributor Author

Thanks for the comment and for offering help! @eallovon

You're right, this PR is a bit stuck, mostly because it is not really a priority on our side anymore, so I don't get to invest time in this currently.

To move this PR forward, I would say the following must be done in this order (can be done by anyone):

  1. Fix failing PJSIP + T.38 tests. Some might simply be failing because some of the new config options need different defaults for backward compatibility reasons - see this comment, and some might need changes to the Testsuite PR.
  2. Together with maintainers, figure out how to resolve backwards compatibility issues.
    E.g. If this PR goes into Asterisk 23/24, can we then drop the old config options if the defaults remain the same? If not, then we have to figure out how both sets of options can coexist (and then this PR can always be merged into the release branches). Since it's not urgent for us, removing the old options would be our preference, since it's simpler for us. A merge into master would have to be done before mid August for it to be in Asterisk 23.

If you can help with any of the above, that would be greatly appreciated. And we can also talk about how to correctly attribute the work.

PS:

even for asterisk 22 it seems too late ?

With the breaking changes that we have currently, yes. If we can make this PR backwards compatible and make it coexist with the existing options, then it can be merged anytime. If the maintainers allow the removal of the old options for Asterisk 23/24, then it would have to be merged into master by mid August. See the bottom of the Asterisk Versions page.

did you have a look at what is failing for T.38

Not in detail, no.

But then without clear cause, the alaw (probably from the endpoint configuration) comes back and asterisk stops the call because it can't transcode g729 to alaw

I'm not sure I fully understood the scenario, but it seems like this scenario should work even without ACN. The way you described it that sounds more like a bug to me, but I'm not sure.

@eallovon

Copy link
Copy Markdown

Hi,

Thanks a lot for your detailed answer.

But then without clear cause, the alaw (probably from the endpoint configuration) comes back and asterisk stops the call because it can't transcode g729 to alaw

I'm not sure I fully understood the scenario, but it seems like this scenario should work even without ACN. The way you described it that sounds more like a bug to me, but I'm not sure.

In the end I focused mainly on your comment here trying to figure out if it could be a bug.

tl;dr

it may be a bug, but it never really worked. Though, in the process of debugging it I found that setting asymmetric_rtp_codec=true fixed my issue. To be honest, therefore, our interest in this PR decreased quite a lot, and I'm not sure we would be able to help more then. I'm sorry for that.

FTR, the longer explanation

Given the following configuration

[test_codec](!)
allow = !all,alaw,g729
direct_media=no
incoming_call_offer_pref=remote
outgoing_call_offer_pref=remote_merge

[alice](test_codec)
type = endpoint
auth=alice
aors=alice

[bob](test_codec)
type = endpoint
auth=bob
aors=bob

As I said in my previous message, with current version of asterisk (20.11 for example), if caller sends an offer with g729>g722>alaw, asterisk correctly sends an offer to callee with g729>alaw (respecting caller order, filtered from codec unknown in caller/callee configuration).
And when callee answers with g729, asterisk correctly answers with g729 too.

But then the communication fails to establish with the message

WARNING[70]: channel.c:5765 set_format: Unable to find a codec translation path: (alaw) -> (g729)
WARNING[70]: channel.c:5765 set_format: Unable to find a codec translation path: (g729) -> (alaw)

What I found is that the option outgoing_call_offer_pref=remote_merge never worked till asterisk 18.10.0 which has fix res_pjsip_sdp_rtp: Preserve order of RTP codecs
Before asterisk 18.10.0, with the above setting, asterisk would offer alaw > g729 to the callee (so what was configured instead of something related to what was offered by the remote).
Since asterisk 18.10 it behaves the same with the configuration I provided : that is, the offer from asterisk correctly follows what is set in the {incoming,outgoing}_call_offer_pref options, but then the call fails to establish when there is no translation path.

What I discovered when adding some log in the code set_caps function of res/res_pjsip_sdp_rtp.c tracing the different codec capability computed, is that in fact the code was going inside the !asymmetric_rtp_codec part of the if-else which introduces a "best" capabilities (this option was introduced way before by pjsip: Extend 'asymmetric_rtp_codec' option to include us changing.. This is this "best" cap which was introducing back the alaw from 'nowhere'.

Therefore in our case, adding asymmetric_rtp_codec=yes in our configuration solved our issue: we still have the correct offer from asterisk and the call this time establishes without. Asterisk no longer tries to translate between alaw and g729 a call that was negotiated in g729 both sides.

As I said, I'm afraid that if we don't find another culprit our interest in this PR will fade.

@khoegh

khoegh commented Feb 4, 2025

Copy link
Copy Markdown
Contributor

I had a crash today.
I have lots of calls between the same endpoints which look similar without crashes. I think it is a timing issue.
The called endpoint responded 183 followed by 180 after 0.000358 second. (Both had SDP)
Unfortunately I'm unable to fix the code.
Hope the following can help anyone interested.

#0 ast_stream_topology_get_first_stream_by_type (type=AST_MEDIA_TYPE_AUDIO, topology=0x7f9038a9d5a8) at stream.c:976
976 if (stream->type == type
[Current thread is 1 (Thread 0x7f8fee524700 (LWP 3461580))]
(gdb) p stream
$1 = (struct ast_stream *) 0x7f9785dda96a
(gdb) p stream->type
Cannot access memory at address 0x7f9785dda96a

(gdb) bt
#0 ast_stream_topology_get_first_stream_by_type (type=AST_MEDIA_TYPE_AUDIO, topology=0x7f9038a9d5a8) at stream.c:976
#1 ast_stream_topology_create_resolved (pending_topology=pending_topology@entry=0x7f907cc439f8, configured_topology=0x7f9038a9d5a8, prefs=prefs@entry=0x157b30c, error_message=error_message@entry=0x7f8fee51eca0) at stream.c:1046
#2 0x00007f90b0298c69 in chan_pjsip_indicate (ast=0x7f903a1ee050, condition=14, data=0x7f907cc439f8, datalen=0) at chan_pjsip.c:1836
#3 0x00007f9104a6d138 in wait_for_answer (in=in@entry=0x7f903a1ee050, out_chans=out_chans@entry=0x7f8fee51fde0, to_answer=to_answer@entry=0x7f8fee51fda0, to_progress=to_progress@entry=0x7f8fee51fda4,
peerflags=peerflags@entry=0x7f8fee520938, opt_args=opt_args@entry=0x7f8fee520080, pa=0x7f8fee5202e0, num_in=0x7f8fee51fe00, result=0x7f8fee51fdac, dtmf_progress=, mf_progress=,
mf_wink=, sf_progress=, sf_wink=, hearpulsing=0, ignore_cc=1, forced_clid=0x7f8fee51fe50, stored_clid=0x7f8fee51fea0, config=) at app_dial.c:1611
#4 0x00007f9104a71b64 in dial_exec_full (chan=0x7f903a1ee050, data=, peerflags=peerflags@entry=0x7f8fee520938, continue_exec=continue_exec@entry=0x0) at app_dial.c:3052
#5 0x00007f9104a74179 in dial_exec (chan=, data=) at app_dial.c:3596
#6 0x000000000052d2c6 in pbx_exec (c=c@entry=0x7f903a1ee050, app=app@entry=0x121cde0, data=data@entry=0x7f8fee521a80 "PJSIP/23456789@sip-peer,180,iS(43200)b(Dial_Handler^23456789^1)")
at /usr/local/src/asterisk/asterisk-18.25.0+acn/include/asterisk/strings.h:67
#7 0x0000000000522202 in pbx_extension_helper (c=c@entry=0x7f903a1ee050, context=0x7f903a1eea90 "Trunk", exten=exten@entry=0x7f903a1eeae0 "23456789", priority=priority@entry=11, label=label@entry=0x0,
callerid=callerid@entry=0x7f8fd41e4350 "98765432", action=E_SPAWN, found=0x7f8fee523b04, combined_find_spawn=1, con=0x0) at pbx.c:2948
#8 0x0000000000523ccb in ast_spawn_extension (combined_find_spawn=1, found=0x7f8fee523b04, callerid=0x7f8fd41e4350 "98765432", priority=11, exten=0x7f903a1eeae0 "23456789", context=, c=0x7f903a1ee050) at pbx.c:4203
#9 __ast_pbx_run (c=c@entry=0x7f903a1ee050, args=args@entry=0x0) at pbx.c:4377
#10 0x00000000005252bb in pbx_thread (data=data@entry=0x7f903a1ee050) at pbx.c:4701
#11 0x00000000005a6e29 in dummy_start (data=) at utils.c:1607
#12 0x00007f91097921ca in start_thread () from /usr/lib64/libpthread.so.0
#13 0x00007f91071568d3 in clone () from /usr/lib64/libc.so.6

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

Thanks for the report @khoegh! The hint about the 183 and 180 with SDP is very useful and likely has to do with it. Unfortunately, currently I won't have time to look into the details.

@github-actions

github-actions Bot commented Feb 5, 2025

Copy link
Copy Markdown

REMINDER: If this PR applies to other branches, please add a comment with the appropriate "cherry-pick-to" headers as per the Create a Pull Request process.

If you don't want it cherry-picked, please add a comment with cherry-pick-to: none so we don't keep asking.

If, after adding "cherry-pick-to" comments, you change your mind, please edit the comment to DELETE the header lines and add cherry-pick-to: none.

The currently active branches are now 20, 21, 22 and master.

1 similar comment
@github-actions

github-actions Bot commented Feb 5, 2025

Copy link
Copy Markdown

REMINDER: If this PR applies to other branches, please add a comment with the appropriate "cherry-pick-to" headers as per the Create a Pull Request process.

If you don't want it cherry-picked, please add a comment with cherry-pick-to: none so we don't keep asking.

If, after adding "cherry-pick-to" comments, you change your mind, please edit the comment to DELETE the header lines and add cherry-pick-to: none.

The currently active branches are now 20, 21, 22 and master.

@github-actions

github-actions Bot commented Feb 7, 2025

Copy link
Copy Markdown

REMINDER: If this PR applies to other branches, please add a comment with the appropriate cherry-pick-to headers as per the Create a Pull Request process.

If you don't want it cherry-picked, please add a comment with so we don't keep asking.

If, after adding cherry-pick-to comments, you change your mind, please edit the comment to DELETE the header lines and add .

The currently active branches are now 20, 21, 22 and master.

@khoegh

khoegh commented Feb 12, 2025

Copy link
Copy Markdown
Contributor

I've had 7 crashes in as many weeks, handling several hundred thousand calls pr day.
180 is always received less than a ms after the 183 which makes asterisk crash.
There are small variations, where the crash is.
chan_pjsip.c:1611 is in common, which is:
ast_channel_tech(in)->indicate(in, AST_CONTROL_PROGRESS, top, 0);
guarded by ast_channel_lock(in);

When 180/SDP is received, there is no channel lock, and it is using the "old"
ast_indicate(in, AST_CONTROL_RINGING);

I had a crash today. I have lots of calls between the same endpoints which look similar without crashes. I think it is a timing issue. The called endpoint responded 183 followed by 180 after 0.000358 second. (Both had SDP) Unfortunately I'm unable to fix the code. Hope the following can help anyone interested.

#0 ast_stream_topology_get_first_stream_by_type (type=AST_MEDIA_TYPE_AUDIO, topology=0x7f9038a9d5a8) at stream.c:976 976 if (stream->type == type [Current thread is 1 (Thread 0x7f8fee524700 (LWP 3461580))] (gdb) p stream $1 = (struct ast_stream *) 0x7f9785dda96a (gdb) p stream->type Cannot access memory at address 0x7f9785dda96a

(gdb) bt #0 ast_stream_topology_get_first_stream_by_type (type=AST_MEDIA_TYPE_AUDIO, topology=0x7f9038a9d5a8) at stream.c:976 #1 ast_stream_topology_create_resolved (pending_topology=pending_topology@entry=0x7f907cc439f8, configured_topology=0x7f9038a9d5a8, prefs=prefs@entry=0x157b30c, error_message=error_message@entry=0x7f8fee51eca0) at stream.c:1046 #2 0x00007f90b0298c69 in chan_pjsip_indicate (ast=0x7f903a1ee050, condition=14, data=0x7f907cc439f8, datalen=0) at chan_pjsip.c:1836 #3 0x00007f9104a6d138 in wait_for_answer (in=in@entry=0x7f903a1ee050, out_chans=out_chans@entry=0x7f8fee51fde0, to_answer=to_answer@entry=0x7f8fee51fda0, to_progress=to_progress@entry=0x7f8fee51fda4, peerflags=peerflags@entry=0x7f8fee520938, opt_args=opt_args@entry=0x7f8fee520080, pa=0x7f8fee5202e0, num_in=0x7f8fee51fe00, result=0x7f8fee51fdac, dtmf_progress=, mf_progress=, mf_wink=, sf_progress=, sf_wink=, hearpulsing=0, ignore_cc=1, forced_clid=0x7f8fee51fe50, stored_clid=0x7f8fee51fea0, config=) at app_dial.c:1611

@khoegh

khoegh commented Mar 4, 2025

Copy link
Copy Markdown
Contributor

I've used the following patch for a couple of weeks (~5M calls) without crashes and haven't noticed any side effects.

--- a/apps/app_dial.c   2024-12-02 15:34:43.486312781 +0100
+++ b/apps/app_dial.c   2025-02-12 16:03:57.472812221 +0100
@@ -1574,7 +1574,11 @@
                                                        ast_channel_early_bridge(in, c);
                                                }
                                                if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK) && ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) {
-                                                       ast_indicate(in, AST_CONTROL_RINGING);
+                                                       struct ast_stream_topology *top = ao2_bump(ast_channel_get_stream_topology(c));
+                                                       ast_channel_lock(in);
+                                                       ast_channel_tech(in)->indicate(in, AST_CONTROL_RINGING, top, 0);
+                                                       ast_channel_unlock(in);
+                                                       ao2_ref(top, -1);
                                                        pa->sentringing++;
                                                }
                                                if (!sent_ring) {

I've had 7 crashes in as many weeks, handling several hundred thousand calls pr day. 180 is always received less than a ms after the 183 which makes asterisk crash. There are small variations, where the crash is. chan_pjsip.c:1611 is in common, which is: ast_channel_tech(in)->indicate(in, AST_CONTROL_PROGRESS, top, 0); guarded by ast_channel_lock(in);

When 180/SDP is received, there is no channel lock, and it is using the "old" ast_indicate(in, AST_CONTROL_RINGING);

I had a crash today. I have lots of calls between the same endpoints which look similar without crashes. I think it is a timing issue. The called endpoint responded 183 followed by 180 after 0.000358 second. (Both had SDP) Unfortunately I'm unable to fix the code. Hope the following can help anyone interested.
#0 ast_stream_topology_get_first_stream_by_type (type=AST_MEDIA_TYPE_AUDIO, topology=0x7f9038a9d5a8) at stream.c:976 976 if (stream->type == type [Current thread is 1 (Thread 0x7f8fee524700 (LWP 3461580))] (gdb) p stream $1 = (struct ast_stream *) 0x7f9785dda96a (gdb) p stream->type Cannot access memory at address 0x7f9785dda96a
(gdb) bt #0 ast_stream_topology_get_first_stream_by_type (type=AST_MEDIA_TYPE_AUDIO, topology=0x7f9038a9d5a8) at stream.c:976 #1 ast_stream_topology_create_resolved (pending_topology=pending_topology@entry=0x7f907cc439f8, configured_topology=0x7f9038a9d5a8, prefs=prefs@entry=0x157b30c, error_message=error_message@entry=0x7f8fee51eca0) at stream.c:1046 #2 0x00007f90b0298c69 in chan_pjsip_indicate (ast=0x7f903a1ee050, condition=14, data=0x7f907cc439f8, datalen=0) at chan_pjsip.c:1836 #3 0x00007f9104a6d138 in wait_for_answer (in=in@entry=0x7f903a1ee050, out_chans=out_chans@entry=0x7f8fee51fde0, to_answer=to_answer@entry=0x7f8fee51fda0, to_progress=to_progress@entry=0x7f8fee51fda4, peerflags=peerflags@entry=0x7f8fee520938, opt_args=opt_args@entry=0x7f8fee520080, pa=0x7f8fee5202e0, num_in=0x7f8fee51fe00, result=0x7f8fee51fdac, dtmf_progress=, mf_progress=, mf_wink=, sf_progress=, sf_wink=, hearpulsing=0, ignore_cc=1, forced_clid=0x7f8fee51fe50, stored_clid=0x7f8fee51fea0, config=) at app_dial.c:1611

@eallovon

Copy link
Copy Markdown

Hi @maximilianfridrich

I'm back again on this PR.
Last time I wrote

our interest in this PR decreased quite a lot, and I'm not sure we would be able to help more then. I'm sorry for that.

In fact after more test the workaround I had found did not work for all cases so we had to add this ACN patch to our asterisk.

After some discussion with our customer he is willing to help on this ACN work in order for this PR to - hopefully - be included in asterisk. So we have now some time to work on this.

As you said last time :

To move this PR forward, I would say the following must be done in this order (can be done by anyone):

1. Fix failing PJSIP + T.38 tests. Some might simply be failing because some of the new config options need different defaults for backward compatibility reasons - see [this comment](https://github.com/asterisk/asterisk/pull/285#issuecomment-1698949588), and some might need changes to the [Testsuite PR](https://github.com/asterisk/testsuite/pull/20).

2. Together with maintainers, figure out how to resolve backwards compatibility issues.
   E.g. If this PR goes into Asterisk 23/24, can we then drop the old config options if the defaults remain the same? If not, then we have to figure out how both sets of options can coexist (and then this PR can always be merged into the release branches). Since it's not urgent for us, removing the old options would be our preference, since it's simpler for us. A merge into master would have to be done [before mid August](https://docs.asterisk.org/About-the-Project/Asterisk-Versions/) for it to be in Asterisk 23.

We are going in the next couple of weeks to try to address the first point, namely Fix failing PJSIP + T.38 tests.

Two questions:

  • first to take over the work we thought that the easiest would probably that we work on our side and maybe re-open PR (asterisk and testsuite) based on yours, mentioning your work ; if that's ok for you ?
  • second, for the collaboration, if we have any question on the current implementation are you still willing to help on this PR ? do you have any sort of time to perhaps review our proposal ? etc.

looking forward to reading you

@maximilianfridrich

maximilianfridrich commented Aug 18, 2025

Copy link
Copy Markdown
Contributor Author

@eallovon That sounds great, thank you for picking this up!

  • That works for me, please either just keep my commits in your PR and add more commits or add me as a Co-Author to the commit in your PR (or add yourself as a Co-Author to my commit 😉).
  • Yes, I will certainly make time for review and I can also help if there's questions. I will likely won't have much time to actively code, but I will happily try out your changes and review/make suggestions.

@btriller

Copy link
Copy Markdown
Contributor

@eallovon I added some changes to master...btriller:asterisk:acn

@eallovon

Copy link
Copy Markdown

Hi @maximilianfridrich

So we were able to take some time to work on the T.38 issue.

Our analysis seem to indicate that there is some kind of desynchronization between the media session and the T.38 part which leads asterisk to refuse the re-INVITE.
(As a reminder a T.38 session is established via a re-INVITE containing the T.38 in the SDP after a first INVITE (with usually alaw codec) was accepted between caller and callee).

From what we understood this desynchronization seem to come from these modifications in the PR which pushes to the stream handling only a copy of the media_state.
This is what leads the T.38 not to be aware of some modifications.

From our analysis this copy does not really seem necessary (?) and from our tests, going backward, on this media_state copy restores the T.38 scenarios without breaking the ACN as far as we tried.

Regarding the asterisk testsuite it seems to pass all the T.38 related test (except the directmedia_reinvite_t38 scenario).
Before looking deeper in this scenario we would be interested by your feedback on this patch which, in fact, only go backward on these changes.

Here is the proposed patch. Please don't hesitate to put it in your PR (we don't really care of being mentioned etc.) so that the testsuite could be rerun and we could check everything's fine :

Index: src/asterisk/res/res_pjsip_session.c
===================================================================
--- src.orig/asterisk/res/res_pjsip_session.c
+++ src/asterisk/res/res_pjsip_session.c
@@ -2870,11 +2870,7 @@ static int sdp_requires_deferral(struct
                /* As this is only called on an incoming SDP offer before processing it is not possible
                 * for streams and their media sessions to exist.
                 */
-               media_state = ast_sip_session_media_state_clone(session->pending_media_state);
-               if (!media_state) {
-                       return -1;
-               }
-               if (ast_stream_topology_set_stream(media_state->topology, i, stream)) {
+               if (ast_stream_topology_set_stream(session->pending_media_state->topology, i, stream)) {
                        ast_stream_free(stream);
                        return -1;
                }
@@ -2887,7 +2883,7 @@ static int sdp_requires_deferral(struct
                        }
                }
 
-               session_media = ast_sip_session_media_state_add(session, media_state, ast_media_type_from_str(media), i);
+               session_media = ast_sip_session_media_state_add(session, session->pending_media_state, ast_media_type_from_str(media), i);
                if (!session_media) {
                        return -1;
                }
@@ -3027,8 +3023,6 @@ static pj_bool_t session_reinvite_on_rx_
                return PJ_FALSE;
        }
 
-       ast_sip_session_media_state_reset(session->pending_media_state);
-
        pjsip_rx_data_clone(rdata, 0, &session->deferred_reinvite);
 
        return PJ_TRUE;

Any feedback would be appreciated, thanks

@eallovon

eallovon commented Oct 1, 2025

Copy link
Copy Markdown

hi @maximilianfridrich

We continued to look into the T.38 tests and specifically the directmedia_reinvite_t38 which was the last failing.

In the end this second patch fix also the directmedia_reinvite_t38 test

Index: asterisk/channels/chan_pjsip.c
===================================================================
--- asterisk.orig/channels/chan_pjsip.c
+++ asterisk/channels/chan_pjsip.c
@@ -208,10 +208,16 @@ static enum ast_rtp_glue_result chan_pjs
                return AST_RTP_GLUE_RESULT_FORBID;
        }
 
+       /*
+        * Forbid native RTP only when T.38 is actually in use or negotiating.
+        */
        datastore = ast_sip_session_get_datastore(channel->session, "t38");
        if (datastore) {
+               enum ast_sip_session_t38state t38state = channel->session->t38state;
                ao2_ref(datastore, -1);
-               return AST_RTP_GLUE_RESULT_FORBID;
+               if (t38state != T38_DISABLED) {
+                       return AST_RTP_GLUE_RESULT_FORBID;
+               }
        }
 
        endpoint = channel->session->endpoint;

So normally with these two patches it should fix the T.38 scenario and the first task we were trying to accomplish to move this PR forward.

Did you have any time to look at the first patch we suggested ? Any comments ?

Again don't hesitate to integrate it in your PR to see if it actually fixes the testsuite.

Or do you prefer that I open a new PR ?

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

Hi @eallovon. Sorry for the late response, I'm a little swamped these days. The patches look good! I just added them as a commit to this branch and triggered the CI testsuite runs here on GitHub. Let's see what they report.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attention! This pull request may contain issues that could prevent it from being accepted. Please review the checklist below and take the recommended action. If you believe any of these are not applicable, just add a comment and let us know.

  • An Alembic change was detected but a commit message UpgradeNote with at least one of the 'alembic', 'database' or 'schema' keywords wasn't found. Please add an UpgradeNote to the commit message that mentions one of those keywords notifying users that there's a database schema change. (alembic-upgrade)

Documentation:

@github-actions

github-actions Bot commented Oct 1, 2025

Copy link
Copy Markdown

Workflow PRCheck failed
master-ari1: FAILED TEST: rest_api/applications/channel_subscriptions/basic_subscription
master-ari1: FAILED TEST: rest_api/applications/channel_subscriptions/originate_to_dialplan/non_local_channels
master-ari1: FAILED TEST: rest_api/applications/channel_subscriptions/originate_to_other_stasis_app/local_channels
master-ari1: FAILED TEST: rest_api/applications/channel_subscriptions/originate_to_other_stasis_app/non_local_channels
master-ari1: FAILED TEST: rest_api/applications/channel_subscriptions/originate_to_stasis_app/local_channels
master-ari1: FAILED TEST: rest_api/applications/double_subscribe_device_state
master-ari1: FAILED TEST: rest_api/applications/errors
master-ari1: FAILED TEST: rest_api/applications/event_filter/allowed
master-ari1: FAILED TEST: rest_api/applications/event_filter/both
master-ari1: FAILED TEST: rest_api/applications/event_filter/disallowed
master-ari1: FAILED TEST: rest_api/applications/stasisstatus
master-ari1: FAILED TEST: rest_api/applications/subscribe_all
master-ari1: FAILED TEST: rest_api/applications/subscribe_all_bridge
master-ari1: FAILED TEST: rest_api/applications/subscribe_bridge
master-ari1: FAILED TEST: rest_api/applications/subscribe_device_state
master-ari1: FAILED TEST: rest_api/applications/subscribe_endpoint/nominal/resource
master-ari1: FAILED TEST: rest_api/applications/subscribe_endpoint/nominal/tech
master-ari1: FAILED TEST: rest_api/applications/subscribe_endpoint/off_nominal/unknown_resource
master-ari1: FAILED TEST: rest_api/applications/subscribe_endpoint/off_nominal/unknown_tech
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/create
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/_delete
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/get
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/pjsip/delete_aor
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/pjsip/modify_aor_to_qualified
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/pjsip/modify_aor_to_unqualified
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/pjsip/modify_endpoint
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/registration_cleanup
master-ari1: FAILED TEST: rest_api/asterisk/config/dynamic/update
master-ari1: FAILED TEST: rest_api/asterisk/logging/add_log
master-ari1: FAILED TEST: rest_api/asterisk/logging/get_logging
master-ari1: FAILED TEST: rest_api/asterisk/logging/rotate_log
master-ari1: FAILED TEST: rest_api/asterisk/modules/get_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/get_modules
master-ari1: FAILED TEST: rest_api/asterisk/modules/get_unknown_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/load_already_loaded_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/load_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/load_unknown_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/reload_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/reload_unknown_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/reload_unloaded_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/unload_already_unloaded_module
master-ari1: FAILED TEST: rest_api/asterisk/modules/unload_module
master-ari1: FAILED TEST: rest_api/authentication
master-ari1: FAILED TEST: rest_api/bridges/add_recording_channel
master-ari1: FAILED TEST: rest_api/bridges/bridge_by_id
master-ari1: FAILED TEST: rest_api/bridges/bridge_record
master-ari1: FAILED TEST: rest_api/bridges/_delete
master-ari1: FAILED TEST: rest_api/bridges/error
master-ari1: FAILED TEST: rest_api/bridges/hangup
master-ari1: FAILED TEST: rest_api/bridges/happy
master-ari1: FAILED TEST: rest_api/bridges/id_propagate
master-ari1: FAILED TEST: rest_api/bridges/move
master-ari1: FAILED TEST: rest_api/bridges/no_id_propagate
master-ari1: FAILED TEST: rest_api/bridges/playback/basic
master-ari1: FAILED TEST: rest_api/bridges/playback/forward
master-ari1: FAILED TEST: rest_api/bridges/playback/reverse
master-ari1: FAILED TEST: rest_api/bridges/playback/tones
master-ari1: FAILED TEST: rest_api/bridges/softmix_unhold
master-ari1: FAILED TEST: rest_api/bridges/unhappy
master-ari1: FAILED TEST: rest_api/bridges/video
master-ari1: FAILED TEST: rest_api/events/subscribe_ws
master-ari1: FAILED TEST: rest_api/events/user/channel
master-ari1: FAILED TEST: rest_api/events/user/invalid
master-ari1: FAILED TEST: rest_api/events/user/multi
master-ari1: FAILED TEST: rest_api/events/variables
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_app/non_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_app/two_channel_different_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_app/two_channel_same_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_bridge/different_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_bridge/non_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_bridge/non_stasis_bridge
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_bridge/same_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_bridge/two_channel_different_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_bridge/stasis_bridge/two_channel_same_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_redirect/stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/ami_redirect/stasis_bridge
master-ari1: FAILED TEST: rest_api/external_interaction/ami_redirect/stasis_bridge_direct_originate
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/non_stasis_app_to_stasis_bridge
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/non_stasis_bridge_to_stasis_bridge
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_non_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_app_ari_only
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_bridge/different_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_bridge/same_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_bridge/same_stasis_app_accepted
master-ari1: FAILED TEST: rest_api/external_interaction/blind_transfer/stasis_bridge_to_different_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/blind_transfer/stasis_bridge_to_non_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/blind_transfer/stasis_bridge_to_same_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/bridge_app/stasis_bridge
master-ari1: FAILED TEST: rest_api/external_interaction/bridge_app/x_option/stasis_bridge
master-ari1: FAILED TEST: rest_api/mailbox/baseline
master-ari1: FAILED TEST: rest_api/message/endpoint/recv
master-ari1: FAILED TEST: rest_api/message/endpoint/send
master-ari1: FAILED TEST: rest_api/message/mixed_endpoint_technology_subscriptions
master-ari1: FAILED TEST: rest_api/message/technology/recv
master-ari1: FAILED TEST: rest_api/message/technology/send
master-ari1: FAILED TEST: rest_api/move
master-ari2: FAILED TEST: rest_api/channels/connected_line_update
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/bridge/bridge_after_answer
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/bridge/bridge_early_media
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/bridge/bridge_then_dial
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/bridge/bridge_while_ringing
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/create/nominal
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/create/off_nominal
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/dial/nominal/basic
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/dial/nominal/_continue
master-ari2: FAILED TEST: rest_api/channels/create_dial_bridge/dial/off_nominal
master-ari2: FAILED TEST: rest_api/channels/create_duplicate_id
master-ari2: FAILED TEST: rest_api/channels/external_media/nominal
master-ari2: FAILED TEST: rest_api/channels/hold/hold_intercept
master-ari2: FAILED TEST: rest_api/channels/originate
master-ari2: FAILED TEST: rest_api/channels/originate_duplicate_id
master-ari2: FAILED TEST: rest_api/channels/originate_then_continue
master-ari2: FAILED TEST: rest_api/channels/originate_to_dialplan
master-ari2: FAILED TEST: rest_api/channels/originate_to_pjsip_endpoint
master-ari2: FAILED TEST: rest_api/channels/originate_with_id
master-ari2: FAILED TEST: rest_api/channels/originate_with_linkedid
master-ari2: FAILED TEST: rest_api/channels/originate_with_vars
master-ari2: FAILED TEST: rest_api/channels/playback/basic
master-ari2: FAILED TEST: rest_api/channels/playback/forward
master-ari2: FAILED TEST: rest_api/channels/playback/lists/basic
master-ari2: FAILED TEST: rest_api/channels/playback/lists/forward
master-ari2: FAILED TEST: rest_api/channels/playback/lists/reverse
master-ari2: FAILED TEST: rest_api/channels/playback/lists/stop
master-ari2: FAILED TEST: rest_api/channels/playback/reverse
master-ari2: FAILED TEST: rest_api/channels/playback/to_channel_in_bridge
master-ari2: FAILED TEST: rest_api/channels/playback/to_channel_in_bridge_hangup
master-ari2: FAILED TEST: rest_api/channels/playback/tones
master-ari2: FAILED TEST: rest_api/channels/playback/tones_w_tonezone
master-ari2: FAILED TEST: rest_api/channels/redirect/nominal
master-ari2: FAILED TEST: rest_api/channels/redirect/off_nominal
master-ari2: FAILED TEST: rest_api/channels/rtp_statistics/basic
master-ari2: FAILED TEST: rest_api/channels/snoop_id
master-ari2: FAILED TEST: rest_api/channels/snoop_spy
master-ari2: FAILED TEST: rest_api/channels/snoop_whisper
master-ari2: FAILED TEST: rest_api/content_type
master-ari2: FAILED TEST: rest_api/_continue
master-ari2: FAILED TEST: rest_api/danger/dangerous
master-ari2: FAILED TEST: rest_api/danger/safe
master-ari2: FAILED TEST: rest_api/device_state/add_invalid
master-ari2: FAILED TEST: rest_api/device_state/add_remove
master-ari2: FAILED TEST: rest_api/device_state/change
master-ari2: FAILED TEST: rest_api/device_state/list
master-ari2: FAILED TEST: rest_api/websocket/outbound_websocket/local_ari_user_read_only
master-ari2: FAILED TEST: rest_api/websocket/outbound_websocket/per_call
master-ari2: FAILED TEST: rest_api/websocket/outbound_websocket/persistent
master-ari2: FAILED TEST: rest_api/websocket/rest_over_websocket/bad_requests
master-ari2: FAILED TEST: rest_api/websocket/rest_over_websocket/parallel_requests
master-ari2: FAILED TEST: rest_api/websocket/rest_over_websocket/single_requests
master-extra_gates: FAILED TEST: extra_gates/tenant_id/tenant_id_ami
master-extra_gates: FAILED TEST: extra_gates/tenant_id/tenant_id_ari
master-extra_gates: FAILED TEST: extra_gates/tenant_id/tenant_id_dialplan
master-fax: FAILED TEST: fax/pjsip/ast_2016_003
master-fax: FAILED TEST: fax/pjsip/directmedia_reinvite_t38
master-fax: FAILED TEST: fax/pjsip/gateway_g711_t38
master-fax: FAILED TEST: fax/pjsip/gateway_native_t38
master-fax: FAILED TEST: fax/pjsip/gateway_t38_g711_rx
master-fax: FAILED TEST: fax/pjsip/gateway_t38_g711_tx
master-fax: FAILED TEST: fax/pjsip/maxdatagram/both
master-fax: FAILED TEST: fax/pjsip/maxdatagram/callee
master-fax: FAILED TEST: fax/pjsip/maxdatagram/caller
master-fax: FAILED TEST: fax/pjsip/maxdatagram/none
master-fax: FAILED TEST: fax/pjsip/t38
master-fax: FAILED TEST: fax/pjsip/t38_1xx_response
master-fax: FAILED TEST: fax/pjsip/t38_fast_reject
master-fax: FAILED TEST: fax/pjsip/t38_initial_offer
master-fax: FAILED TEST: fax/pjsip/t38_with_auth
master-fax: FAILED TEST: fax/pjsip/t38_zero_port
master-local_iax2_mgr: FAILED TEST: channels/iax2/acl_call
master-local_iax2_mgr: FAILED TEST: channels/iax2/basic_call
master-local_iax2_mgr: FAILED TEST: channels/iax2/encrypted_calls/md5
master-local_iax2_mgr: FAILED TEST: channels/iax2/encrypted_calls/rsa
master-local_iax2_mgr: FAILED TEST: channels/iax2/encrypted_calls/rsa_dynamic
master-local_iax2_mgr: FAILED TEST: channels/local/local_app
master-local_iax2_mgr: FAILED TEST: channels/local/local_call
master-local_iax2_mgr: FAILED TEST: channels/local/local_holding_bridge
master-local_iax2_mgr: FAILED TEST: channels/local/local_loop
master-local_iax2_mgr: FAILED TEST: channels/local/local_optimize_away
master-local_iax2_mgr: FAILED TEST: channels/local/local_removed_audio_stream_request
master-local_iax2_mgr: FAILED TEST: manager/acl_login
master-local_iax2_mgr: FAILED TEST: manager/bridge_actions
master-local_iax2_mgr: FAILED TEST: manager/config/advanced
master-local_iax2_mgr: FAILED TEST: manager/config/basic
master-local_iax2_mgr: FAILED TEST: manager/config/no_preserve_effective_context
master-local_iax2_mgr: FAILED TEST: manager/config/restricted
master-local_iax2_mgr: FAILED TEST: manager/connected_line
master-local_iax2_mgr: FAILED TEST: manager/danger/dangerous
master-local_iax2_mgr: FAILED TEST: manager/danger/safe
master-local_iax2_mgr: FAILED TEST: manager/device_state_changed
master-local_iax2_mgr: FAILED TEST: manager/device_state_list
master-local_iax2_mgr: FAILED TEST: manager/exten_state_list
master-local_iax2_mgr: FAILED TEST: manager/login
master-local_iax2_mgr: FAILED TEST: manager/manager_vars
master-local_iax2_mgr: FAILED TEST: manager/mixmonitor/mixmonitor_basic
master-local_iax2_mgr: FAILED TEST: manager/mixmonitor/mixmonitor_id
master-local_iax2_mgr: FAILED TEST: manager/originate
master-local_iax2_mgr: FAILED TEST: manager/playdtmf
master-local_iax2_mgr: FAILED TEST: manager/presence_state_changed
master-local_iax2_mgr: FAILED TEST: manager/presence_state_list
master-local_iax2_mgr: FAILED TEST: manager/redirect/dual/app
master-local_iax2_mgr: FAILED TEST: manager/redirect/dual/bridge/different
master-local_iax2_mgr: FAILED TEST: manager/redirect/dual/bridge/same
master-local_iax2_mgr: FAILED TEST: manager/redirect/single/app
master-local_iax2_mgr: FAILED TEST: manager/redirect/single/bridge
master-local_iax2_mgr: FAILED TEST: manager/sendtext
master-local_iax2_mgr: FAILED TEST: manager/status
master-local_iax2_mgr: FAILED TEST: manager/status_all_vars
master-local_iax2_mgr: FAILED TEST: manager/userevent
master-pjs1: FAILED TEST: channels/pjsip/call_pickup
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/common_codecs_default
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/common_codecs_union
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/late_offer_progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/late_offer_ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/common_codecs_default
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/common_codecs_union
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/late_offer_progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/late_offer_ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/no_common_codecs
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/no_common_codecs_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/no_common_codecs_prevent
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/no_common_codecs_prevent_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/progress_no_180
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/reverse_order
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/local_channels/ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/no_common_codecs
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/no_common_codecs_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/no_common_codecs_prevent
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/no_common_codecs_prevent_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/progress_no_180
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/reverse_order
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio/ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/common_codecs_default
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/common_codecs_union
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/late_offer_progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/late_offer_ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/common_codecs_default
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/common_codecs_union
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/late_offer_progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/late_offer_ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/no_common_codecs
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/no_common_codecs_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/no_common_codecs_prevent
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/no_common_codecs_prevent_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/progress_no_180
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/reverse_order
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/local_channels/ringing
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/no_common_codecs
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/no_common_codecs_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/no_common_codecs_prevent
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/no_common_codecs_prevent_early
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/progress
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/progress_no_180
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/reverse_order
master-pjs1: FAILED TEST: channels/pjsip/codec_negotiation/audio_video/ringing
master-pjs1: FAILED TEST: channels/pjsip/config_wizard/hints
master-pjs1: FAILED TEST: channels/pjsip/config_wizard/phone
master-pjs1: FAILED TEST: channels/pjsip/config_wizard/registration
master-pjs1: FAILED TEST: channels/pjsip/config_wizard/trunk
master-pjs1: FAILED TEST: channels/pjsip/configuration/duplicate_sections
master-pjs1: FAILED TEST: channels/pjsip/configuration/happy_config
master-pjs1: FAILED TEST: channels/pjsip/connected_line/connected_line_allow
master-pjs1: FAILED TEST: channels/pjsip/connected_line/connected_line_no_send
master-pjs1: FAILED TEST: channels/pjsip/connected_line/connected_line_no_trust
master-pjs1: FAILED TEST: channels/pjsip/content_disposition
master-pjs1: FAILED TEST: channels/pjsip/cseq_method
master-pjs1: FAILED TEST: channels/pjsip/geolocation/incoming/basic
master-pjs1: FAILED TEST: channels/pjsip/geolocation/incoming/profile_precedence
master-pjs1: FAILED TEST: channels/pjsip/geolocation/round_trip/gml
master-pjs1: FAILED TEST: channels/pjsip/handle_options_request
master-pjs1: FAILED TEST: channels/pjsip/handle_options_request_drop_options
master-pjs1: FAILED TEST: channels/pjsip/headers/anonymous_from_basic_call
master-pjs1: FAILED TEST: channels/pjsip/headers/no_contact
master-pjs1: FAILED TEST: channels/pjsip/headers/non_anonymous_from_basic_call
master-pjs1: FAILED TEST: channels/pjsip/history_info/diversion_request
master-pjs1: FAILED TEST: channels/pjsip/history_info/diversion_response_181
master-pjs1: FAILED TEST: channels/pjsip/history_info/history_info_request
master-pjs1: FAILED TEST: channels/pjsip/history_info/history_info_response_181
master-pjs1: FAILED TEST: channels/pjsip/history_info/no_diversion_response_181
master-pjs1: FAILED TEST: channels/pjsip/hold
master-pjs1: FAILED TEST: channels/pjsip/hold_ice
master-pjs1: FAILED TEST: channels/pjsip/hold_inactive
master-pjs1: FAILED TEST: channels/pjsip/mediasec/registration
master-pjs1: FAILED TEST: channels/pjsip/message/message_basic
master-pjs1: FAILED TEST: channels/pjsip/message/message_basic_drop_options
master-pjs1: FAILED TEST: channels/pjsip/message/message_confbridge
master-pjs1: FAILED TEST: channels/pjsip/message/message_context
master-pjs1: FAILED TEST: channels/pjsip/message/message_cust_hdr
master-pjs1: FAILED TEST: channels/pjsip/message/message_destination_parsing
master-pjs1: FAILED TEST: channels/pjsip/message/message_from
master-pjs1: FAILED TEST: channels/pjsip/message/message_in_dialog
master-pjs1: FAILED TEST: channels/pjsip/message/message_retrans
master-pjs1: FAILED TEST: channels/pjsip/message/message_send_ami
master-pjs1: FAILED TEST: channels/pjsip/message/message_to_uri
master-pjs1: FAILED TEST: channels/pjsip/moh_passthru_inactive
master-pjs1: FAILED TEST: channels/pjsip/multipart_empty_part
master-pjs1: FAILED TEST: channels/pjsip/nat/rewrite_contact/contact_request
master-pjs1: FAILED TEST: channels/pjsip/nat/rewrite_contact/contact_response
master-pjs1: FAILED TEST: channels/pjsip/nat/rewrite_contact/route_set_reinvite
master-pjs1: FAILED TEST: channels/pjsip/nat/rewrite_contact/route_set_request
master-pjs1: FAILED TEST: channels/pjsip/nat/rewrite_contact/route_set_response
master-pjs1: FAILED TEST: channels/pjsip/non_negotiated_frame_SSRC_change
master-pjs1: FAILED TEST: channels/pjsip/oli/header_parameter
master-pjs1: FAILED TEST: channels/pjsip/oli/uri_parameter
master-pjs1: FAILED TEST: channels/pjsip/one_touch_recording/endpoint_beep
master-pjs1: FAILED TEST: channels/pjsip/one_touch_recording/endpoint_config
master-pjs1: FAILED TEST: channels/pjsip/one_touch_recording/features_config/features_configured
master-pjs1: FAILED TEST: channels/pjsip/one_touch_recording/features_config/features_not_configured
master-pjs1: FAILED TEST: channels/pjsip/parameters/outgoing_uri
master-pjs1: FAILED TEST: channels/pjsip/publish/asterisk_event_devicestate
master-pjs1: FAILED TEST: channels/pjsip/publish/asterisk_event_mwi
master-pjs1: FAILED TEST: channels/pjsip/publish/dialog_info_xml
master-pjs1: FAILED TEST: channels/pjsip/publish/presence_pidf
master-pjs1: FAILED TEST: channels/pjsip/publish/presence_xpidf
master-pjs1: FAILED TEST: channels/pjsip/qualify/auth
master-pjs1: FAILED TEST: channels/pjsip/qualify/basic
master-pjs1: FAILED TEST: channels/pjsip/qualify/call_unreachable
master-pjs1: FAILED TEST: channels/pjsip/qualify/max_initial_qualify_time
master-pjs1: FAILED TEST: channels/pjsip/qualify/no_qualify
master-pjs1: FAILED TEST: channels/pjsip/qualify/qualify_timeout
master-pjs1: FAILED TEST: channels/pjsip/use_callerid_contact/no_privacy/contact_user
master-pjs1: FAILED TEST: channels/pjsip/use_callerid_contact/no_privacy/use_caller_contact_disabled
master-pjs1: FAILED TEST: channels/pjsip/use_callerid_contact/no_privacy/use_caller_contact_enabled
master-pjs1: FAILED TEST: channels/pjsip/use_callerid_contact/privacy/contact_user
master-pjs1: FAILED TEST: channels/pjsip/use_callerid_contact/privacy/use_caller_contact_disabled
master-pjs1: FAILED TEST: channels/pjsip/use_callerid_contact/privacy/use_caller_contact_enabled
master-pjs1: FAILED TEST: channels/pjsip/user_eq_phone
master-pjs2: FAILED TEST: channels/pjsip/accountcode
master-pjs2: FAILED TEST: channels/pjsip/acl_call
master-pjs2: FAILED TEST: channels/pjsip/all_codecs_on_empty_reinvite/early_offer
master-pjs2: FAILED TEST: channels/pjsip/all_codecs_on_empty_reinvite/late_offer
master-pjs2: FAILED TEST: channels/pjsip/allow_overlap
master-pjs2: FAILED TEST: channels/pjsip/allow_sending_180_after_183/disabled
master-pjs2: FAILED TEST: channels/pjsip/allow_sending_180_after_183/enabled
master-pjs2: FAILED TEST: channels/pjsip/ami/pjsip_notify/cli
master-pjs2: FAILED TEST: channels/pjsip/ami/pjsip_notify/content
master-pjs2: FAILED TEST: channels/pjsip/ami/pjsip_notify/custom_headers
master-pjs2: FAILED TEST: channels/pjsip/ami/pjsip_notify/reserved_headers
master-pjs2: FAILED TEST: channels/pjsip/ami/pjsip_notify/to_uri
master-pjs2: FAILED TEST: channels/pjsip/ami/pjsip_qualify
master-pjs2: FAILED TEST: channels/pjsip/ami/show_endpoint
master-pjs2: FAILED TEST: channels/pjsip/ami/show_endpoints
master-pjs2: FAILED TEST: channels/pjsip/ami/show_registration_inbound_contact_statuses
master-pjs2: FAILED TEST: channels/pjsip/ami/show_registrations_inbound
master-pjs2: FAILED TEST: channels/pjsip/ami/show_registrations_outbound
master-pjs2: FAILED TEST: channels/pjsip/ami/show_subscriptions
master-pjs2: FAILED TEST: channels/pjsip/auth/uac/multiple_realm_multiple_digest
master-pjs2: FAILED TEST: channels/pjsip/auth/uac/single_realm_multiple_digest
master-pjs2: FAILED TEST: channels/pjsip/auth/uac/single_realm_single_digest
master-pjs2: FAILED TEST: channels/pjsip/auth/uas/auth_security_events
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/chan_is_avail
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_aor
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_channel
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_channel2
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_contact
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_dtmfmode
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_endpoint
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_hangup
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_header
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_notify
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_parse_uri
master-pjs2: FAILED TEST: channels/pjsip/dialplan_functions/pjsip_session_refresh
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_basic
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_basic_drop_options
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_caller_id
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_request
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_request_drop_options
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_response
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_response_181
master-pjs2: FAILED TEST: channels/pjsip/diversion/diversion_response_drop_options
master-pjs2: FAILED TEST: channels/pjsip/diversion/history_info_request
master-pjs2: FAILED TEST: channels/pjsip/diversion/history_info_response_181
master-pjs2: FAILED TEST: channels/pjsip/diversion/no_diversion_response_181
master-pjs2: FAILED TEST: channels/pjsip/dtmf_incompatible
master-pjs2: FAILED TEST: channels/pjsip/dtmf_info_fallback
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_audio_8k_digits_bob
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_diff
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_match
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_match_8k_digits
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_8k_priority_diff
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_8k_priority_match
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice_asym
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_bob
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_recognition
master-pjs2: FAILED TEST: channels/pjsip/ice/ice_not_offered
master-pjs2: FAILED TEST: channels/pjsip/ice/ice_offered
master-pjs2: FAILED TEST: channels/pjsip/identify/header
master-pjs2: FAILED TEST: channels/pjsip/identify/header_or_ip
master-pjs2: FAILED TEST: channels/pjsip/identify/header_ordering_header_ip
master-pjs2: FAILED TEST: channels/pjsip/identify/header_ordering_ip_header
master-pjs2: FAILED TEST: channels/pjsip/identify/ordering
master-pjs2: FAILED TEST: channels/pjsip/identify/port_matching/port
master-pjs2: FAILED TEST: channels/pjsip/identify/port_matching/port_with_mask
master-pjs2: FAILED TEST: channels/pjsip/identify/request_uri
master-pjs2: FAILED TEST: channels/pjsip/ignore_183_wo_sdp/ignore_disabled/with_sdp
master-pjs2: FAILED TEST: channels/pjsip/ignore_183_wo_sdp/ignore_disabled/wo_sdp
master-pjs2: FAILED TEST: channels/pjsip/ignore_183_wo_sdp/ignore_enabled/with_sdp
master-pjs2: FAILED TEST: channels/pjsip/ignore_183_wo_sdp/ignore_enabled/wo_sdp
master-pjs2: FAILED TEST: channels/pjsip/in_dialog_invite_replaces
master-pjs2: FAILED TEST: channels/pjsip/in_dialog_options
master-pjs2: FAILED TEST: channels/pjsip/incoming_call_on_second_transport
master-pjs2: FAILED TEST: channels/pjsip/incoming_calls_without_auth
master-pjs2: FAILED TEST: channels/pjsip/info_dtmf
master-pjs2: FAILED TEST: channels/pjsip/info_empty
master-pjs2: FAILED TEST: channels/pjsip/invalid_uris
master-pjs2: FAILED TEST: channels/pjsip/tel_uri/basic_call
master-pjs2: FAILED TEST: channels/pjsip/transfers/asterisk/endpoint/redirect
master-pjs2: FAILED TEST: channels/pjsip/transfers/asterisk/endpoint/refer
master-pjs2: FAILED TEST: channels/pjsip/transfers/asterisk/uri/redirect
master-pjs2: FAILED TEST: channels/pjsip/transfers/asterisk/uri/refer
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_local
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_local_blonde
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_local_semi_attended_transfer_record_route
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_local
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_local_app
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_local_blonde
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_remote
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/callee_direct_media
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/callee_refer_only
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/callee_with_hold
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_direct_media
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_refer_only
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_with_hold
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_with_hold_481
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_with_hold_drop_options
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/disallow
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/goto_on_blindxfr
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/immediate_ok_notify
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/off_nominal/transferer_reinvite
master-pjs2: FAILED TEST: channels/pjsip/transport/reuse/invite
master-pjs2: FAILED TEST: channels/pjsip/transport/reuse/notify
master-pjs2: FAILED TEST: channels/pjsip/transport/reuse/options
master-pjs2: FAILED TEST: channels/pjsip/transport/symmetric/invite
master-pjs2: FAILED TEST: channels/pjsip/transport/symmetric/notify
master-pjs2: FAILED TEST: channels/pjsip/transport/symmetric/options
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/md5/ident_by_header
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/md5/ident_by_host
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/md5/ident_by_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/md5/ident_by_user_drop_options
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/userpass/ident_by_auth_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/userpass/ident_by_header
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/userpass/ident_by_host
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/userpass/ident_by_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/authed/userpass/ident_by_user_drop_options
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/peer_in_dialog_auths
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/unauthed/ident_by_anonymous
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/unauthed/ident_by_header
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/unauthed/ident_by_host
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/unauthed/ident_by_host_only
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/unauthed/ident_by_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/nominal/unauthed/ident_by_user_drop_options
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/bare_ack
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/incompatible_codecs
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/invalid_number
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/invalid_sdp
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/md5
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/unknown_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/userpass/ident_by_auth_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/incoming/off_nominal/userpass/wrong_credentials
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/auth
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/dialstring
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/early_media
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/echo
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/from_user
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/nat
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/peer_in_dialog_auths
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/nominal/playback
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/off_nominal/bob_does_not_answer
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/off_nominal/bob_does_not_exist
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/off_nominal/bob_incompatible_codecs
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/off_nominal/bob_is_busy
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/off_nominal/bob_is_busy_at
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/outgoing/off_nominal/call_canceled
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/add_remove_sources
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/alice_initiated/alice_hangs_up
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/alice_initiated/bob_hangs_up
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/alice_initiated/requested_capabilities
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/two_servers
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/video_bidirectional_to_unidirectional
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/video_unidirectional_to_bidirectional
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/off_nominal/authed/bob_rejects
master-pjs4: FAILED TEST: channels/pjsip/refer_send_to_vm
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/config_options/maximum_expiration
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/config_options/minimum_expiration
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/config_options/remove_existing
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/config_options/remove_unavailable
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/contact_acl/ipv4
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/mixed/unauthed
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/multiple_contacts/authed
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/multiple_contacts/unauthed
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/multiple_contacts/unauthed_drop_options
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/path
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/regcontext
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/single_contact/authed
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/single_contact/unauthed
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/single_contact/unauthed_drop_options
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/unregister/all_contacts
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/unregister/multiple_contacts
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/unregister/single_contact
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/nominal/user_agent
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/off_nominal/max_contacts
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/off_nominal/no_contact_header
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/off_nominal/unregister/no_expires_header
master-pjs4: FAILED TEST: channels/pjsip/registration/inbound/off_nominal/wrong_password
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/auth_loop
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/failover
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/fatal_retry
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/forbidden_retry
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/interval_too_brief
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/line_parameter
master-pjs4: FAILED TEST: channels/pjsip/registration/outbound/unregister/unauthed
master-pjs4: FAILED TEST: channels/pjsip/reinvite_after_bye
master-pjs4: FAILED TEST: channels/pjsip/reinvite_early
master-pjs4: FAILED TEST: channels/pjsip/reinvite_pending
master-pjs4: FAILED TEST: channels/pjsip/rel100/incoming/peer_supported_not_used
master-pjs4: FAILED TEST: channels/pjsip/rel100/incoming/peer_supported_require
master-pjs4: FAILED TEST: channels/pjsip/rel100/incoming/peer_supported_used
master-pjs4: FAILED TEST: channels/pjsip/rel100/outgoing/peer_supported_not_used
master-pjs4: FAILED TEST: channels/pjsip/rel100/outgoing/peer_supported_used
master-pjs4: FAILED TEST: channels/pjsip/resolver/a
master-pjs4: FAILED TEST: channels/pjsip/resolver/aaaa
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/explicit_transport_configured
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/order
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/preference
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/preference_failover
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/restricted_transport
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/transport_tcp
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/transport_udp
master-pjs4: FAILED TEST: channels/pjsip/resolver/naptr/transport_unspecified
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/explicit_transport_configured
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/in_dialog/timeout
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/in_dialog/transport_tcp
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/in_dialog/transport_udp
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/in_dialog/transport_unspecified
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/out_of_dialog/timeout
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/out_of_dialog/transport_tcp
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/out_of_dialog/transport_udp
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/failover/out_of_dialog/transport_unspecified
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/priority
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/transport_tcp
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/transport_udp
master-pjs4: FAILED TEST: channels/pjsip/resolver/srv/transport_unspecified
master-pjs4: FAILED TEST: channels/pjsip/rpid_immediate
master-pjs4: FAILED TEST: channels/pjsip/rtcp/rtcp_mux_callee/rtcp_mux_enabled
master-pjs4: FAILED TEST: channels/pjsip/rtcp/rtcp_mux_callee/rtcp_mux_not_enabled
master-pjs4: FAILED TEST: channels/pjsip/rtcp/rtcp_mux_caller/rtcp_mux_not_offered
master-pjs4: FAILED TEST: channels/pjsip/rtcp/rtcp_mux_caller/rtcp_mux_offered
master-pjs4: FAILED TEST: channels/pjsip/rtp/asymmetric_rtp_codec/off
master-pjs4: FAILED TEST: channels/pjsip/rtp/asymmetric_rtp_codec/on
master-pjs4: FAILED TEST: channels/pjsip/rtp/bind_rtp_to_media_address
master-pjs4: FAILED TEST: channels/pjsip/rtp/rtp_keepalive/base
master-pjs4: FAILED TEST: channels/pjsip/rtp/rtp_keepalive/direct_media
master-pjs4: FAILED TEST: channels/pjsip/rtp/timeout
master-pjs4: FAILED TEST: channels/pjsip/rtp/timeout_hold
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video_app/decline
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video/accept/bundled
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video/accept/multiple_audio
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video/accept/multiple_video
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video/decline/basic
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video/decline/multiple_audio
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio_video/decline/multiple_video
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio/accept
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio/add
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio/decline
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/audio/remove
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/video/accept
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/video/add
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/video/decline
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/multiple_media_stream/video/remove
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/single_media_stream/audio/avpf
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/single_media_stream/audio/basic
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/single_media_stream/audio/packetization
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/nominal/single_media_stream/video/basic
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/codec_mismatch
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/hold_declined
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/initial_declined
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/single_media_stream/audio/avpf_mismatch
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/single_media_stream/audio/codec_mismatch
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/single_media_stream/audio/initial_declined
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/media_offer/incoming_outgoing
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/media_offer/incoming_refresh
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/media_offer/outgoing
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/webrtc/goog_remb
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/nominal/all_ciphers_verify_certs
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/nominal/allow_wildcard_certs/cn
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/nominal/allow_wildcard_certs/san
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/nominal/limited_ciphers_verify_certs
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/nominal/two_CAs_no_verify_certs
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/nominal/two_CAs_verify_certs
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/off_nominal/dtls_verify_failure
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/off_nominal/no_dtls_ciphers_in_common
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/off_nominal/no_sips_ciphers_in_common
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/calls/off_nominal/sips_verify_failure
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/optimistic_srtp/mandatory_with_optimistic_offer
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/optimistic_srtp/optimistic_with_mandatory_offer
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/optimistic_srtp/optimistic_with_no_crypto
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/optimistic_srtp/optimistic_with_optimistic_offer
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/srtp_negotiation
master-pjs5: FAILED TEST: channels/pjsip/secure_calling/srtp_not_loaded
master-pjs5: FAILED TEST: channels/pjsip/session_timers/session_timer_minse
master-pjs5: FAILED TEST: channels/pjsip/set_var
master-pjs5: FAILED TEST: channels/pjsip/statsd/contacts
master-pjs5: FAILED TEST: channels/pjsip/statsd/registrations
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_acl_fail
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_anon_callerid
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_exp_ca
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_fail_return_reason
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_no_identity
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_sig_fail
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_success
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_success_unknown_tn
master-pjs5: FAILED TEST: channels/pjsip/stir_shaken/stir_shaken_tn_mismatch
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/ast_restart
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/below_min_expiry
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/large_number_of_accept_headers
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mismatch
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/conflict
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/missing_aor
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/mwi_aggregate
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/mwi_devstate
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/no_accept_header
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/sub_setup_teardown
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/sub_setup_teardown_drop_options
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/sub_term_and_removal
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/unsolicited/incoming
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/unsolicited/initial_notify
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/unsolicited/notify_after_register
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/mwi/unsolicited/notify_after_register_realtime
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/no_event_header
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/devstate_repeat
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/dialog_info_xml
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/digium_presence
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/no_accept_header
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/presencestate_repeat
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/presencestate_repeat_okay
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/resubscribe
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/unsubscribe
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/verify_bodies/verify_pidf
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/presence/verify_bodies/verify_xpidf
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/batched/basic
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/batched/multiple_resources_single_change
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/batched/resubscription_interruption
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/batched/single_resource_multiple_changes
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/batched/termination_interruption
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/initial_notify
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/partial_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/resubscribe_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/subscription_establishment
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/mwi/termination_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/batched/basic
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/batched/multiple_resources_single_change
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/batched/resubscription_interruption
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/batched/single_resource_multiple_changes
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/batched/termination_interruption
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/mwi/list_does_not_exist
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/mwi/no_list_resources_exist
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/mwi/resource_duplication
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/mwi/some_list_resources_exist
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/mwi/subscribe_wo_eventlist_support
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/mwi/subscribe_wrong_event_header
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/presence/list_does_not_exist
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/presence/no_list_resources_exist
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/presence/resource_duplication
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/presence/some_list_resources_exist
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/presence/subscribe_wo_eventlist_support
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists/off_nominal/presence/subscribe_wrong_event_header
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/batched
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/full_state_alice
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/full_state_carol
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/initial_notify
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/partial_state_alice
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/partial_state_carol
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/resubscribe_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/subscription_establishment
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/mwi/termination_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/batched
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/full_state_alice
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/full_state_carol
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/initial_notify
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/partial_state_alice
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/partial_state_carol
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/resubscribe_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/subscription_establishment
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/nominal/presence/termination_full_state
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/off_nominal/mwi/resource_duplication
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/off_nominal/mwi/shared_name_w_list_support
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/off_nominal/mwi/shared_name_wo_list_support
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/off_nominal/presence/resource_duplication
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/off_nominal/presence/shared_name_w_list_support
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/rls/lists_of_lists/off_nominal/presence/shared_name_wo_list_support
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/subscribe_context
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/unallowed
master-pjs5: FAILED TEST: channels/pjsip/subscriptions/unknown_event_package

@eallovon

eallovon commented Oct 8, 2025

Copy link
Copy Markdown

hi @maximilianfridrich

I had a quick look at the failure. I searched for incoming_call_offer_pref in the repo and if I understand well the failure is du to the inclusion present in res/res_pjsip/pjsip_manager.xml.

This diff should do the trick (as pjsip_manager.xml already references the new options) :

diff --git a/res/res_pjsip/pjsip_manager.xml b/res/res_pjsip/pjsip_manager.xml
index 9f2cf634c5..50861ade33 100644
--- a/res/res_pjsip/pjsip_manager.xml
+++ b/res/res_pjsip/pjsip_manager.xml
@@ -638,9 +638,6 @@
                                <parameter name="Ignore183WithoutSdp">
                                        <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='ignore_183_without_sdp']/synopsis/node())"/></para>
                                </parameter>
-                               <parameter name="IncomingCallOfferPref">
-                                       <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='incoming_call_offer_pref']/synopsis/node())"/></para>
-                               </parameter>
                                <parameter name="IncomingMwiMailbox">
                                        <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='incoming_mwi_mailbox']/synopsis/node())"/></para>
                                </parameter>

Advanced Codec Negotiation is now implemented for the dial application,
pjsip channels and local channels.

Resolves: asterisk#223

UpgradeNote: The two pjsip.conf options "incoming_call_offer_pref" and
"outgoing_call_offer_pref" have been removed. Instead, the new options
"codec_prefs_incoming_answer", "codec_prefs_incoming_offer",
"codec_prefs_outgoing_answer", "codec_prefs_outgoing_offer" must be
used. Even if the old settings were not used, this could break existing
deployments as the default ACN options are now in use and they might
behave differently in some call flows (e.g. by default, pending codecs
are always preferred, not the endpoint configuration).

UserNote: The Advanced Codec Negotiation feature is now implemented.
@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

multiple-commits: interim

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

Thank you for your efforts @eallovon. Currently, I still don't have the capacity to work on this unfortunately. I wish I could be of more help.

@github-actions

github-actions Bot commented Oct 9, 2025

Copy link
Copy Markdown

Workflow PRCheck failed
master-app_dial: FAILED TEST: apps/dial/preserve_top
master-fax: FAILED TEST: fax/pjsip/t38_initial_offer
master-local_iax2_mgr: FAILED TEST: manager/bridge_actions
master-pjs1: FAILED TEST: channels/pjsip/connected_line/connected_line_allow
master-pjs1: FAILED TEST: channels/pjsip/connected_line/connected_line_no_send
master-pjs1: FAILED TEST: channels/pjsip/connected_line/connected_line_no_trust
master-pjs1: FAILED TEST: channels/pjsip/hold
master-pjs1: FAILED TEST: channels/pjsip/hold_ice
master-pjs1: FAILED TEST: channels/pjsip/hold_inactive
master-pjs1: FAILED TEST: channels/pjsip/moh_passthru_inactive
master-pjs1: FAILED TEST: channels/pjsip/nat/rewrite_contact/route_set_reinvite
master-pjs2: FAILED TEST: channels/pjsip/all_codecs_on_empty_reinvite/early_offer
master-pjs2: FAILED TEST: channels/pjsip/all_codecs_on_empty_reinvite/late_offer
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_audio_8k_digits_bob
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_diff
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_8k_priority_diff
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice_asym
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_bob
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_local
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_local_blonde
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_local_semi_attended_transfer_record_route
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/callee_remote
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_local
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_local_app
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_local_blonde
master-pjs2: FAILED TEST: channels/pjsip/transfers/attended_transfer/nominal/caller_remote
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/callee_refer_only
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/callee_with_hold
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_refer_only
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_with_hold
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_with_hold_481
master-pjs2: FAILED TEST: channels/pjsip/transfers/blind_transfer/caller_with_hold_drop_options
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/add_remove_sources
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/video_bidirectional_to_unidirectional
master-pjs3: FAILED TEST: channels/pjsip/basic_calls/two_parties/nominal/video_unidirectional_to_bidirectional
master-pjs4: FAILED TEST: channels/pjsip/rtp/timeout_hold
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/codec_mismatch
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/hold_declined

@eallovon

eallovon commented Nov 3, 2025

Copy link
Copy Markdown

hello

Just for information we're still investigating why our suggested patches failed quite some tests in the testsuite.
It seems that:

  1. the patch we sent was done on top of other patches we have on the T.38 which make the whole work together
  2. and also that our patch create some problem with some re-INVITE scenario

Sorry for this and sorry for the "no news" since a few weeks.
We're still trying to figure this out and I'm also working on quite some other topics so it's a bit on the side that we're able to move this forward.

I hope to be able give more news in a not to far future ... 😅

@eallovon

Copy link
Copy Markdown

hello,

So I'm back with a new patch that should fix most of the failing tests.

Attached is a new patch that should apply on top of your branch.
fix-ACN-reinvite-for-upstream.patch

It mainly fixes the re-INVITE scenario where it was needed to distinguish whether it was a T.38 scenario or not when refreshing the session.

I re-ran the testsuite (but mostly on the tests that failed last time) and here are the results compared between your initial PR, your PR with our first patches (current state of your PR) and then with this new attached patch (see table at the end).
So in the end we have:

  • tests that were passing on your PR now pass again (like the blind_transfer)
  • at least 3 new t38 tests should pass
  • and then some tests don't pass at all (like dtmf_sdp_48k_audio_8k_digits_bob) (did not investigate for the moment)

Could you please integrate this new patch in your PR so that we could see what the real testsuite says.

I hope the real testsuite will give us the same results.
Then there are still some T38 case to fix. We may be able to invest a bit more time on this (and on the backward compatibility) but we will see.

Regards,

Appendix

Test result I had :

Test pr285 mfridrich pr285 mfridrich + patch1-2 (Fix ACN for T.38) pr285 mfridrich + patch1-3
apps/dial/preserve_top ✅️ ❌️ ✅️
channels/pjsip/all_codecs_on_empty_reinvite/early-offer ✅️ ❌️ ✅️
channels/pjsip/all_codecs_on_empty_reinvite/late-offer ✅️ ❌️ ✅️
channels/pjsip/basic_calls/two_parties/nominal/add_remove_sources ✅️ ❌️ ✅️
channels/pjsip/basic_calls/two_parties/nominal/video_bidirectional_to_unidirectional ✅️ ❌️ ✅️
channels/pjsip/basic_calls/two_parties/nominal/video_unidirectional_to_bidirectional ✅️ ❌️ ✅️
channels/pjsip/connected_line/connected_line_allow ✅️ ❌️ ✅️
channels/pjsip/connected_line/connected_line_no_send ✅️ ❌️ ✅️
channels/pjsip/connected_line/connected_line_no_trust ✅️ ❌️ ✅️
channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_audio_8k_digits_bob ❌️ ❌️ ❌️
channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_diff ❌️ ❌️ ❌️
channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_8k_priority_diff ❌️ ❌️ ❌️
channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice ❌️ ❌️ ❌️
channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice_asym ❌️ ❌️ ❌️
channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_bob ❌️ ❌️ ❌️
channels/pjsip/hold ✅️ ❌️ ✅️
channels/pjsip/hold_ice ✅️ ❌️ ✅️
channels/pjsip/hold_inactive ✅️ ❌️ ✅️
channels/pjsip/moh_passthru_inactive ✅️ ❌️ ✅️
channels/pjsip/nat/rewrite_contact/route_set_reinvite ✅️ ❌️ ✅️
channels/pjsip/rtp/timeout_hold ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/callee_local ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/callee_local_app SKIPPED SKIPPED SKIPPED
channels/pjsip/transfers/attended_transfer/nominal/callee_local_blonde ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/callee_local_direct_media SKIPPED SKIPPED SKIPPED
channels/pjsip/transfers/attended_transfer/nominal/callee_local_semi_attended_transfer_record_route ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/callee_remote ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/caller_local ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/caller_local_app ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/caller_local_blonde ✅️ ❌️ ✅️
channels/pjsip/transfers/attended_transfer/nominal/caller_local_direct_media SKIPPED SKIPPED SKIPPED
channels/pjsip/transfers/attended_transfer/nominal/caller_remote ✅️ ❌️ ✅️
channels/pjsip/transfers/blind_transfer/callee_refer_only ✅️ ❌️ ✅️
channels/pjsip/transfers/blind_transfer/callee_with_hold ✅️ ❌️ ✅️
channels/pjsip/transfers/blind_transfer/caller_refer_only ✅️ ❌️ ✅️
channels/pjsip/transfers/blind_transfer/caller_with_hold ✅️ ❌️ ✅️
channels/pjsip/transfers/blind_transfer/caller_with_hold_481 ✅️ ❌️ ✅️
channels/pjsip/transfers/blind_transfer/caller_with_hold_drop_options ✅️ ❌️ ✅️
fax/pjsip/directmedia_reinvite_t38 ❌️ ✅️ ✅️
fax/pjsip/t38 ❌️ ✅️ ✅️
fax/pjsip/t38_1xx_response ✅️ ✅️ ✅️
fax/pjsip/t38_enabled_two_reinvite_on_a_leg SKIPPED SKIPPED ❌️
fax/pjsip/t38_enabled_two_reinvite_on_b_leg SKIPPED SKIPPED ❌️
fax/pjsip/t38_fast_reject ❌️ ❌️ ❌️
fax/pjsip/t38_initial_offer ❌️ ❌️ ❌️
fax/pjsip/t38_with_auth ❌️ ✅️ ✅️
fax/pjsip/t38_zero_port ✅️ ✅️ ✅️
manager/bridge_actions ✅️ ❌️ ✅️

@maximilianfridrich

Copy link
Copy Markdown
Contributor Author

Thank you very much @eallovon! I applied your patch to this branch by amending the last commit (with minor restructuring of your patch to fix "ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]" errors). Let's see what the CI-run tests report.

Co-authored-by: Etienne Allovon <eallovon@avencall.com>
@github-actions

Copy link
Copy Markdown

Workflow PRCheck failed
master-fax: FAILED TEST: fax/pjsip/t38_initial_offer
master-pjs1: FAILED TEST: channels/pjsip/geolocation/incoming/basic
master-pjs1: FAILED TEST: channels/pjsip/geolocation/incoming/profile_precedence
master-pjs1: FAILED TEST: channels/pjsip/message/message_redirect
master-pjs1: FAILED TEST: channels/pjsip/message/message_redirect_multiple
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_audio_8k_digits_bob
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_diff
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_8k_priority_diff
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_alice_asym
master-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_negotiation_bob
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/codec_mismatch
master-pjs5: FAILED TEST: channels/pjsip/sdp_offer_answer/incoming/off_nominal/multiple_media_stream/audio_video/hold_declined

@eallovon

Copy link
Copy Markdown

Thank you for the update @maximilianfridrich (and for the fix in our patch).

In the end the test result looks even better than what I had on my side.
If I read correctly:

  • all T38 tests passed (except t38_initial_offer but that may be an easy one)
  • and now we are left with some failures which I think mainly consist of new tests in the testsuite that were added after the PR you did in the testsuite so it's perhaps more a matter of configuration (and of this backward compatibility issue)

@silentindark

Copy link
Copy Markdown
Contributor

@maximilianfridrich Could you please also update testsuite, and re-run tests?

@NickBouwhuis

Copy link
Copy Markdown

Hi @maximilianfridrich, @eallovon,

I dug into the remaining CI failures on this PR and I believe I have root causes for all of them, plus a patch (attached below) that I verified against the testsuite (current testsuite master, Debian 13, --with-pjproject-bundled --enable-dev-mode). With it, all 9 tests from the last PRCheck run that are actually related to this PR pass, and a sweep of previously-passing codec-sensitive tests stays green.

Root cause analysis of the failing gates

master-pjs1 (geolocation ×2, message_redirect ×2) — not caused by this PR

These are simply the branch being ~250 commits behind master. The testsuite tests were updated/added for features that landed in Asterisk master after this branch's base:

  • res_pjsip: 3xx redirect module (2bd999ae5f, d8caa664a8) → message_redirect, message_redirect_multiple
  • res_geolocation/res_pjsip_geolocation updates (5c16412dc4, 2c97fd3ea4) → geolocation/incoming/*

A rebase fixes these four. I test-merged current master: only res/res_pjsip/pjsip_configuration.c conflicts, and trivially.

master-pjs2 (dtmf_sdp ×6) and master-fax (t38_initial_offer) — default behavior regression

All of these tests assert the pre-ACN default negotiation behavior:

  • Answers must follow the endpoint's configured codec order, not the offer's order. E.g. t38_initial_offer offers RTP/AVP 9 8 0 against allow=!all,g722,ulaw,alaw and expects the answer 9 0 8. With codec_prefs_incoming_offer = prefer: pending the answer comes back 9 8 0 and the test fails. Same story for the dtmf_sdp priority tests.
  • Outgoing offers must contain exactly the endpoint's allow list. The _bob tests fail because with codec_prefs_outgoing_offer = prefer: pending, operation: union, the slin/L16 format that the core requests for an AMI Originate gets unioned into the wire offer: Asterisk offers m=audio ... RTP/AVP 10 0 101 (L16 first!) where legacy behavior — and the test — expects 0 101.

This is exactly the backwards-compatibility point @jcolp raised back in 2023 ("default behavior with this change should match previous versions"), and matches @maximilianfridrich's own 2023 analysis that the incoming defaults would have to become prefer: configured. The patch changes the defaults to:

option old default new default
codec_prefs_incoming_offer prefer: pending, operation: intersect prefer: configured, operation: intersect
codec_prefs_incoming_answer prefer: pending, operation: intersect prefer: configured, operation: intersect
codec_prefs_outgoing_offer prefer: pending, operation: union prefer: configured, operation: only_preferred
codec_prefs_outgoing_answer prefer: pending, operation: intersect (unchanged)

prefer: configured, operation: only_preferred for the outgoing offer reproduces the legacy "offer the endpoint's allow list, in configured order" behavior (the resolved stream is exactly the configured caps). Anyone who wants the new pending-preferred behavior can still opt in per endpoint — the point is only that unset options behave like pre-ACN Asterisk.

master-pjs5 (codec_mismatch, hold_declined) — real bugs in handle_incoming_sdp()

Three compounding problems in the no-common-codec path of handle_incoming_sdp():

  1. Whole-SDP abort instead of per-stream decline. When any single stream resolves to empty caps, the code does goto end with handled = 0, i.e. 488s the entire INVITE. The codec-mismatch test's audio-mismatch scenario offers a bad audio stream + a good video stream and expects 200 OK with m=audio 0 and live video (which is what pre-ACN Asterisk does via the SDP handler returning 0). The patch declines just the affected stream via the same path as the existing port-0 decline; if no stream ends up accepted, handled stays 0 and the 488 still happens naturally.
  2. Codec resolution runs on streams the remote already declined. hold-declined's initial offer contains a valid audio stream plus a declined video stream (m=video 0 RTP/AVP 99 34) with codecs that don't match the endpoint. Resolution runs on it before the port-0 check and kills the whole call. The patch skips resolution for desc.port == 0 streams.
  3. Double-free. resolved_stream is declared as RAII_VAR(..., ast_stream_free), but the empty-resolution path also called ast_stream_free(resolved_stream) explicitly before goto end — so a non-NULL stream with empty formats got freed twice. (Possibly related to the crashes @khoegh reported.) The patch drops the explicit free.

Test results

Everything run against current testsuite master. Baseline is this branch as-is (d659d4c92c), reproducing the CI failures 1:1; "patched" is with the attached patch:

Test baseline patched
sdp_offer_answer/.../audio-video/codec-mismatch
sdp_offer_answer/.../audio-video/hold-declined
fax/pjsip/t38_initial_offer
dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_audio_8k_digits_bob
dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_48k_priority_diff
dtmf_sdp/dtmf_sdp_generation/dtmf_sdp_8k_priority_diff
dtmf_sdp/dtmf_sdp_negotiation_alice
dtmf_sdp/dtmf_sdp_negotiation_alice_asym
dtmf_sdp/dtmf_sdp_negotiation_bob

Regression sweep of previously-passing codec-sensitive tests, all still ✅ with the patch: apps/dial/preserve_top, all_codecs_on_empty_reinvite/early-offer, all_codecs_on_empty_reinvite/late-offer, dtmf_sdp_48k_priority_match, dtmf_sdp_48k_priority_match_8k_digits, dtmf_sdp_8k_priority_match, sdp_offer_answer/.../audio/basic, sdp_offer_answer/.../decline/basic, channels/pjsip/hold, fax/pjsip/t38.

Remaining work beyond this patch

  • Rebase onto master (fixes the 4 pjs1 failures; one small conflict).
  • The 2023 review blocker still stands: incoming_call_offer_pref/outgoing_call_offer_pref are removed and the Alembic migration drops their columns. With the compat defaults above, restoring the old options (old options take priority when set, ACN options otherwise, as @jcolp suggested) becomes much more tractable, and the migration could be dropped entirely.
  • The PR checklist bot wants an UpgradeNote containing "alembic"/"database"/"schema" — moot if the migration is dropped.
  • With these defaults, most of the pjsip.conf adaptations in the testsuite PR (pjsip: Add tests for Advanced Codec Negotiation (ACN) testsuite#20) to pre-existing tests should no longer be needed and could be reverted, which also addresses the "please update testsuite" request.
Patch (applies on top of d659d4c92c)
diff --git a/res/res_pjsip/pjsip_config.xml b/res/res_pjsip/pjsip_config.xml
index 960fed1f8b..df0817a46c 100644
--- a/res/res_pjsip/pjsip_config.xml
+++ b/res/res_pjsip/pjsip_config.xml
@@ -106,8 +106,8 @@
 								<para>
 								</para>
 								<enumlist>
-									<enum name="pending"><para>The codec list from the caller. (default)</para></enum>
-									<enum name="configured"><para>The codec list from the endpoint.</para></enum>
+									<enum name="pending"><para>The codec list from the caller.</para></enum>
+									<enum name="configured"><para>The codec list from the endpoint. (default)</para></enum>
 								</enumlist>
 							</enum>
 							<enum name="operation : &lt; intersect | only_preferred | only_nonpreferred &gt;">
@@ -170,17 +170,17 @@
 								<para>
 								</para>
 								<enumlist>
-									<enum name="pending"><para>The codec list from the core. (default)</para></enum>
-									<enum name="configured"><para>The codec list from the endpoint.</para></enum>
+									<enum name="pending"><para>The codec list from the core.</para></enum>
+									<enum name="configured"><para>The codec list from the endpoint. (default)</para></enum>
 								</enumlist>
 							</enum>
 							<enum name="operation : &lt; union | intersect | only_preferred | only_nonpreferred &gt;">
 								<para>
 								</para>
 								<enumlist>
-									<enum name="union"><para>Merge the lists with the preferred codecs first. (default)</para></enum>
-									<enum name="intersect"><para>Only common codecs with the preferred codecs first. (default)</para></enum>
-									<enum name="only_preferred"><para>Use only the preferred codecs.</para></enum>
+									<enum name="union"><para>Merge the lists with the preferred codecs first.</para></enum>
+									<enum name="intersect"><para>Only common codecs with the preferred codecs first.</para></enum>
+									<enum name="only_preferred"><para>Use only the preferred codecs. (default)</para></enum>
 									<enum name="only_nonpreferred"><para>Use only the non-preferred codecs.</para></enum>
 								</enumlist>
 							</enum>
@@ -235,8 +235,8 @@
 								<para>
 								</para>
 								<enumlist>
-									<enum name="pending"><para>The codec list in the received SDP answer. (default)</para></enum>
-									<enum name="configured"><para>The codec list from the endpoint.</para></enum>
+									<enum name="pending"><para>The codec list in the received SDP answer.</para></enum>
+									<enum name="configured"><para>The codec list from the endpoint. (default)</para></enum>
 								</enumlist>
 							</enum>
 							<enum name="operation : &lt; union | intersect | only_preferred | only_nonpreferred &gt;">
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 5f6fa62b3f..7e45c11889 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1269,15 +1269,15 @@ static int codec_prefs_handler(const struct aco_option *opt,
 			return -1;
 		}
 		option_prefs = &endpoint->media.codec_prefs_incoming_offer;
-		default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
+		default_prefer = CODEC_NEGOTIATION_PREFER_CONFIGURED;
 		default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
 	} else if (strcmp(var->name, "codec_prefs_outgoing_offer") == 0) {
 		option_prefs = &endpoint->media.codec_prefs_outgoing_offer;
-		default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
-		default_operation = CODEC_NEGOTIATION_OPERATION_UNION;
+		default_prefer = CODEC_NEGOTIATION_PREFER_CONFIGURED;
+		default_operation = CODEC_NEGOTIATION_OPERATION_ONLY_PREFERRED;
 	} else if (strcmp(var->name, "codec_prefs_incoming_answer") == 0) {
 		option_prefs = &endpoint->media.codec_prefs_incoming_answer;
-		default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
+		default_prefer = CODEC_NEGOTIATION_PREFER_CONFIGURED;
 		default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
 	} else if (strcmp(var->name, "codec_prefs_outgoing_answer") == 0) {
 		option_prefs = &endpoint->media.codec_prefs_outgoing_answer;
@@ -2226,13 +2226,13 @@ int ast_res_pjsip_initialize_configuration(void)
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "suppress_q850_reason_headers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, suppress_q850_reason_headers));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ignore_183_without_sdp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ignore_183_without_sdp));
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_offer",
-		"prefer: pending, operation: intersect, keep: all, transcode: allow",
+		"prefer: configured, operation: intersect, keep: all, transcode: allow",
 		codec_prefs_handler, incoming_offer_codec_prefs_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_outgoing_offer",
-		"prefer: pending, operation: union, keep: all, transcode: allow",
+		"prefer: configured, operation: only_preferred, keep: all, transcode: allow",
 		codec_prefs_handler, outgoing_offer_codec_prefs_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_answer",
-		"prefer: pending, operation: intersect, keep: all",
+		"prefer: configured, operation: intersect, keep: all",
 		codec_prefs_handler, incoming_answer_codec_prefs_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_outgoing_answer",
 		"prefer: pending, operation: intersect, keep: all",
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index da0bfe3d69..bcc8cf80b3 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -877,6 +877,7 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
 		RAII_VAR(struct sdp_handler_list *, handler_list, NULL, ao2_cleanup);
 		struct ast_sip_session_media *session_media = NULL;
 		int res;
+		int no_common_codecs = 0;
 		enum ast_media_type type;
 		struct ast_stream *stream = NULL;
 		pjmedia_sdp_media *remote_stream = sdp->media[i];
@@ -939,16 +940,19 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
 			}
 
 			remote_ast_stream = ast_stream_topology_get_first_stream_by_type(remote_topology, type);
-			if (remote_ast_stream) {
+			if (remote_ast_stream && remote_stream->desc.port) {
 				/* Here we always have a remote offer, so we create a resolved stream using the remote SDP offer
 				 * and the configured endpoint settings codec_prefs_incoming_offer. */
 				configured_stream = ast_stream_topology_get_first_stream_by_type(session->endpoint->media.topology, type);
 				resolved_stream = ast_stream_create_resolved(remote_ast_stream, configured_stream, &session->endpoint->media.codec_prefs_incoming_offer, NULL);
 				if (!resolved_stream || ast_format_cap_empty(ast_stream_get_formats(resolved_stream))) {
-					ast_stream_free(resolved_stream); /* Can handle NULL */
+					/* Decline just this stream below instead of failing the whole
+					 * negotiation. If no stream ends up accepted, the negotiation
+					 * still fails as a whole. resolved_stream is freed by RAII_VAR. */
 					stream = ast_stream_alloc(stream_name, type);
-					handled = 0;
-					SCOPE_EXIT_LOG_EXPR(goto end, LOG_ERROR, "No common codecs between incoming SDP offer and endpoint configuration.\n");
+					no_common_codecs = 1;
+					ast_trace(-1, "%s: No common codecs between incoming SDP offer and endpoint configuration, declining stream\n",
+						ast_sip_session_get_name(session));
 				} else {
 					stream = ast_stream_clone(resolved_stream, stream_name);
 				}
@@ -1007,8 +1011,9 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
 				 ast_sip_session_get_name(session));
 		}
 
-		/* If this stream is already declined mark it as such, or mark it as such if we've reached the limit */
-		if (!remote_stream->desc.port || is_stream_limitation_reached(type, session->endpoint, type_streams)) {
+		/* If this stream is already declined mark it as such, or mark it as such if we've reached
+		 * the limit or no codecs were in common with the endpoint configuration */
+		if (no_common_codecs || !remote_stream->desc.port || is_stream_limitation_reached(type, session->endpoint, type_streams)) {
 			remove_stream_from_bundle(session_media, stream);
 			SCOPE_EXIT_EXPR(continue, "%s: Declining incoming SDP media stream %s'\n",
 				ast_sip_session_get_name(session), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

has-pr-checklist A PR Checklist is present on the PR pr-submit-tests-failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[new-feature]: Advanced Codec Negotiation