There are various reason an entity on either end of the connection might want to send a new offer while maintaining the existing connection. When this happens the entities keep the same ICE tags ( ufrag and pwd ) that they used to set up the connection in the first place regardless their current role ( offer or answer ).
Of the rtpengine ICE flags there are a couple that tell rtpengine to act as an ICE agent. Unfortuantely each time they are invoked they present new ICE tags. In ICE land that is the definition of an ICE restart. Chrome and Firefox drop the connection when they receive the restart request. Firefox gives a very clear error message, chrome not so much." Remote description indicates ICE restart but offer did not request ICE restart"
Is there any way to cofigure around this problem?
Emphasis mine. No it doesn't do that. It generates new attributes only when the call/dialogue is deleted between the invocations, or if the from/to-tags are different (because that would tell rtpengine that it's talking to a different endpoint), or perhaps if there's some other booboo in the signalling to rtpengine that I can't think of right now. So, post a log that shows your signalling.
Cheers
First off we can eliminate Chrome. What I saw previously appears to be unrelated to the ICE thing. But it gets strange. If Twinkle on host A calls WEBRTC on host B and host B then initiates call Hold, host B drops the call. Repeating with host A calling host B , now host B initiates call Hold/Resume, it's all good.
If host B WEBRTC calls host A Twinkle Hold/Resume works fine every which way. If Twinkle is run on host B and WEBRTC is on host A, I can't make Hold/Resume fail. The same web app is used on all the calls. The trouble only occurs with WEBRTC running on host B ( HP laptop ).
In the failure scenario I don't see any dialog change just the ICE tags change. The hosts are side by side on the local wired netwrk.
The dialog
invite
To: <sip:4...@192.168.1.2>
From: <sip:7...@192.168.1.2>;tag=dxosw
Call-ID: qkzhitbmvrhsung@blacky
a=ice-ufrag:88qu07Uu
a=ice-pwd:pbnrSsr1b1gVjYO6g86SavMqOh
answer
To: <sip:4...@192.168.1.2>;tag=cgdbb4qsa2
From: <sip:7...@192.168.1.2>;tag=dxosw
Call-ID: qkzhitbmvrhsung@blacky
a=ice-pwd:760f49d6c39f1d2205ee014160c5fdc3
a=ice-ufrag:16fbb7a9
webrtc goes on Hold
To: <sip:7...@192.168.1.2>;tag=dxosw
From: <sip:4...@192.168.1.2>;tag=cgdbb4qsa2
Call-ID: qkzhitbmvrhsung@blacky
a=ice-ufrag:16fbb7a9
a=ice-pwd:760f49d6c39f1d2205ee014160c5fdc3
answer
To: <sip:7...@192.168.1.2>;tag=dxosw
From: <sip:4...@192.168.1.2>;tag=cgdbb4qsa2
Call-ID: qkzhitbmvrhsung@blacky
a=ice-ufrag:dDiWsVrl
a=ice-pwd:gxFhDjfB4iIfBxi5bR5dIpeVmq
webrtc sends bye
Because I had made some changes in the config script I did some testing to make sure I hadn't introduced some problem. I tested forked calls including calls that involved rtpengine. I tested NAT'd calls and calls that mixed address families. Re-invites were tested in those scenarios. I reverted the changes I had tried with exception of the via branch ID. So that parameter that is passed to rtpengine is the branch ID obtained from the incoming offer rather than the branch index that I had used previously.
I am attaching another file. The previous one involved Firefox which simply dropped the call when it saw the ICE restart. This one is with Chrome which tries to carry on despite the restart. After re-offer ( hold ) and re-offer ( resume ) we are left with one way audio. This time rather than including the sdp from the rtpengine logs I am including the complete messages coming into opensips and leaving. From the rtpengine logs are the messages it got from opensips and also the ICE negotiation stuff.
During the testing I looked at the media flow with Wireshark. In the commentary I showed the relay ports that rtpengine was using to relay the media.
The test in the attached file was a forked call. It wasn't intentional but there happened to be two UAs registered with the same AOR. I noticed that when opensips added its own via it suffixed the branch ID with an integer like abcxyz.0 and abcxyz.1. I am assuming the suffix is the opensips branch index. In this particular instance the answer came from index 1.
It's a bit hard to tell with the truncated/mixed log, but AFAICT the `via-branch` values are all different.
A → B offer: via-branch=z9hG4bKtvnyaxfi -- OK
B → A answer: via-branch=z9hG4bKc05a.b6df8e45.1 -- not OK, this
should be z9hG4bKtvnyaxfi
B → A re-offer: via-branch=z9hG4bK5128999 -- OK
A → B answer: via-branch=z9hG4bKe02e.0e0d6b77.0 -- not OK, this
should be z9hG4bK5128999
In particular it's that last one that makes rtpengine produce a new set of ICE attributes because it thinks the answer is going to a different endpoint (not B).
Below is what the log looks like with correct usage of via-branch tags (but otherwise identical SDPs etc). As you can see the ICE attributes come out the same.
A → B offer
[1640009319.758562] DEBUG: [9192]: [control] Dump for 'offer'
from 127.0.0.1:41313: { "DTLS-fingerprint": "sha-256", "ICE":
"force", "SDES": [ "off" ], "call-id": "9192", "command": "offer",
"flags": [ "generate mid" ], "from-tag": "foo", "rtcp-mux": [
"require" ], "sdp": "v=0
o=twinkle 1739380060 14469997 IN IP4 192.168.1.3
s=-
c=IN IP4 192.168.1.3
t=0 0
m=audio 8000 RTP/AVP 9 0 98 97 8 3 18
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:98 speex/16000
a=rtpmap:97 speex/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:3 GSM/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=ptime:20
", "transport protocol": "UDP/TLS/RTP/SAVPF", "via-branch":
"branch-one" }
[1640009319.760323] DEBUG: [9192]: [control] Response dump for
'offer' to 127.0.0.1:41313: { "sdp": "v=0
o=twinkle 1739380060 14469997 IN IP4 192.168.1.3
s=-
c=IN IP4 192.168.1.87
t=0 0
m=audio 30000 UDP/TLS/RTP/SAVPF 9 0 98 97 8 3 18
a=mid:1
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:98 speex/16000
a=rtpmap:97 speex/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:3 GSM/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=sendrecv
a=rtcp:30000
a=rtcp-mux
a=setup:actpass
a=fingerprint:sha-256
D9:10:52:C6:1E:90:C3:9A:AA:1D:F8:B3:21:71:7B:4B:A7:90:4C:57:F7:35:05:24:F6:44:32:9F:EE:83:4E:14
a=ptime:20
a=ice-ufrag:6BbtP8f1
a=ice-pwd:pjE2JLJiubqNcT8GQgFnN4Ercb
a=candidate:kWKBQ7FGYBqfmVsE 1 UDP 2130706431 192.168.1.87 30000
typ host
a=candidate:fNwLkELnT1ovyK8n 1 UDP 2130706175
2608:fea8:ab00:33::a38 30000 typ host
a=candidate:yEid4l1t2baw4PHS 1 UDP 2130705919
2608:fea8:ab00:33:26da:916f:ef1:1451 30000 typ host
", "result": "ok" }
B → A answer
[1640009322.421105] DEBUG: [9192]: [control] Dump for 'answer'
from 127.0.0.1:38501: { "DTLS-fingerprint": "sha-256", "ICE":
"remove", "call-id": "9192", "command": "answer", "from-tag":
"foo", "rtcp-mux": [ "demux" ], "sdp": "v=0
o=- 6983899188004734691 2 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic: WMS UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
m=audio 56934 UDP/TLS/RTP/SAVPF 9 0 8
c=IN IP4 192.168.1.3
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:3416155287 1 udp 2122262783 2001::f58f 45779 typ host
generation 0 network-id 2
a=candidate:704553097 1 udp 2122194687 192.168.1.3 56934 typ host
generation 0 network-id 1
a=ice-ufrag:YZ3J
a=ice-pwd:2SkZrILTdAoEGWtgZT3FJjsb
a=ice-options:trickle
a=fingerprint:sha-256
A1:D3:50:31:64:0A:2A:C3:39:12:22:32:8A:B1:D9:C8:AB:43:50:30:78:D6:EF:0C:E5:83:37:51:8D:46:BA:F9
a=setup:active
a=mid:1
a=sendrecv
a=msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=rtcp-mux
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=ssrc:1991661435 cname:upYUcx8RyTC4x1lp
a=ssrc:1991661435 msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=ssrc:1991661435 mslabel:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
a=ssrc:1991661435 label:56191062-a8f5-4d97-a903-d233bb6586ed
", "to-tag": "bar", "transport protocol": "RTP/AVP",
"via-branch": "branch-one" }
[1640009322.421622] DEBUG: [9192]: [control] Response dump for
'answer' to 127.0.0.1:38501: { "sdp": "v=0
o=- 6983899188004734691 2 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic: WMS UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
m=audio 30018 RTP/AVP 9 0 8
c=IN IP4 192.168.1.87
a=msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=ssrc:1991661435 cname:upYUcx8RyTC4x1lp
a=ssrc:1991661435 msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=ssrc:1991661435 mslabel:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
a=ssrc:1991661435 label:56191062-a8f5-4d97-a903-d233bb6586ed
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:30019
a=ptime:20
", "result": "ok" }
B → A re-offer
[1640009324.804649] DEBUG: [9192]: [control] Dump for 'offer'
from 127.0.0.1:59072: { "ICE": "remove", "call-id": "9192",
"command": "offer", "from-tag": "bar", "rtcp-mux": [ "demux" ],
"sdp": "v=0
o=- 6983899188004734691 3 IN IP4 127.0.0.1
s=-
t=0 0
a=extmap-allow-mixed
a=msid-semantic: WMS UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
a=group:BUNDLE 1
m=audio 56934 UDP/TLS/RTP/SAVPF 9 0 8 111 63 103 104 106 105 13
110 112 113 126
c=IN IP4 192.168.1.3
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:111 opus/48000/2
a=rtpmap:63 red/48000/2
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=fmtp:111 minptime=10;useinbandfec=1
a=fmtp:63 111/111
a=rtcp:9 IN IP4 0.0.0.0
a=rtcp-fb:111 transport-cc
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2
http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3
http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=setup:actpass
a=mid:1
a=msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=sendonly
a=ice-ufrag:YZ3J
a=ice-pwd:2SkZrILTdAoEGWtgZT3FJjsb
a=fingerprint:sha-256
A1:D3:50:31:64:0A:2A:C3:39:12:22:32:8A:B1:D9:C8:AB:43:50:30:78:D6:EF:0C:E5:83:37:51:8D:46:BA:F9
a=candidate:3416155287 1 udp 2122262783 2001::f58f 45779 typ host
generation 0 network-id 2
a=candidate:704553097 1 udp 2122194687 192.168.1.3 56934 typ host
generation 0 network-id 1
a=ice-options:trickle
a=ssrc:1991661435 cname:upYUcx8RyTC4x1lp
a=ssrc:1991661435 msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=ssrc:1991661435 mslabel:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
a=ssrc:1991661435 label:56191062-a8f5-4d97-a903-d233bb6586ed
a=rtcp-mux
", "to-tag": "foo", "transport protocol": "RTP/AVP",
"via-branch": "branch-two" }
[1640009324.805710] DEBUG: [9192]: [control] Response dump for
'offer' to 127.0.0.1:59072: { "sdp": "v=0
o=- 6983899188004734691 3 IN IP4 127.0.0.1
s=-
t=0 0
a=extmap-allow-mixed
a=msid-semantic: WMS UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
m=audio 30018 RTP/AVP 9 0 8 111 63 103 104 106 105 13 110 112 113
126
c=IN IP4 192.168.1.87
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2
http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3
http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=ssrc:1991661435 cname:upYUcx8RyTC4x1lp
a=ssrc:1991661435 msid:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
56191062-a8f5-4d97-a903-d233bb6586ed
a=ssrc:1991661435 mslabel:UNyBsn7zTPvf0iTi2G9IgA4wVMAfKKAq412S
a=ssrc:1991661435 label:56191062-a8f5-4d97-a903-d233bb6586ed
a=mid:1
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=sendonly
a=rtcp:30019
a=ptime:20
", "result": "ok" }
A → B answer
[1640009326.906187] DEBUG: [9192]: [control] Dump for 'answer'
from 127.0.0.1:47949: { "DTLS-fingerprint": "sha-256", "ICE":
"force", "SDES": [ "off" ], "call-id": "9192", "command":
"answer", "flags": [ "generate mid" ], "from-tag": "bar",
"rtcp-mux": [ "require" ], "sdp": "v=0
o=twinkle 1739380060 14469998 IN IP4 192.168.1.3
s=-
c=IN IP4 192.168.1.3
t=0 0
m=audio 8000 RTP/AVP 9
a=rtpmap:9 G722/8000
a=recvonly
", "to-tag": "foo", "transport protocol": "UDP/TLS/RTP/SAVPF", "via-branch":
"branch-two" }
[1640009326.906475] DEBUG: [9192]: [control] Response dump for
'answer' to 127.0.0.1:47949: { "sdp": "v=0
o=twinkle 1739380060 14469998 IN IP4 192.168.1.3
s=-
c=IN IP4 192.168.1.87
t=0 0
m=audio 30000 UDP/TLS/RTP/SAVPF 9
a=mid:1
a=rtpmap:9 G722/8000
a=recvonly
a=rtcp:30000
a=rtcp-mux
a=setup:passive
a=fingerprint:sha-256
D9:10:52:C6:1E:90:C3:9A:AA:1D:F8:B3:21:71:7B:4B:A7:90:4C:57:F7:35:05:24:F6:44:32:9F:EE:83:4E:14
a=ptime:20
a=ice-ufrag:6BbtP8f1
a=ice-pwd:pjE2JLJiubqNcT8GQgFnN4Ercb
a=ice-options:trickle
a=candidate:kWKBQ7FGYBqfmVsE 1 UDP 2130706431 192.168.1.87 30000
typ host
a=candidate:fNwLkELnT1ovyK8n 1 UDP 2130706175
2608:fea8:ab00:33::a38 30000 typ host
a=candidate:yEid4l1t2baw4PHS 1 UDP 2130705919
2608:fea8:ab00:33:26da:916f:ef1:1451 30000 typ host
a=end-of-candidates
", "result": "ok" }
Oh, at the very end. I thought you had added that yourself. How is "branch-one" generated?
It isn't. I made it up. As I explained before, it doesn't really matter what the value for `via-branch` is, as long as it's unique for offers going to different recipients, and as long as answers can be matched to offers. Using the `branch=` tag from `Via` is a convenient way to achieve this if you use the right header, e.g. the first one for requests and the second one for responses.
INVITE sip:6...@192.168.1.2 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.3;rport;branch=z9hG4bKtvnyaxfi
Max-Forwards: 70
SIP/2.0 200 OKCheers
Record-Route: <sip:[2001::D2B4]:8000;transport=wss;r2=on;lr;ftag=idgzl;mixed-AF;mixed-RTC>
Record-Route: <sip:192.168.1.2;r2=on;lr;ftag=idgzl;mixed-AF;mixed-RTC>
Via: SIP/2.0/WSS [2001::D2B4]:8000;branch=z9hG4bKc05a.b6df8e45.1
Via: SIP/2.0/UDP 192.168.1.3;received=192.168.1.3;rport=5060;branch=z9hG4bKtvnyaxfi
Even if the auto option was working it would be the same as the 1/2 option. The 1/2 option doesn't seem to serve any purpose and in fact causes a problem with forked calls. Rtpeengine prepares a relay dialogue when it gets an offer and is only missing the endpoint of the successful answer. With the 1/2 option the via-branch ID is passed to rtpengine. If the call is forked each offer contains the same value for via-branch.
That is the reason I started I started using "via-branch=extra" with extra value being the branch index. It solved my problem with initial call setup. Rtpengine then prepared multiple dialogues and when the answer comes the correct requirements are applied.
This introduced more trouble. All the dialogues remained up for the duration of the call even though only one was actually in use. A possible solution I tried was to use the 487 response from the unsuccessful callees and using the branch index as before, delete the dialogue. What if one of unsuccessful callees didn't actually require media relay. That branch would be unknown to rtpengine. It actually results in all the dialogues being torn down. When the 487 response is received there is no way of knowing if there was a relay dialogue associated with it.
Dec 30 09:17:47 slim rtpengine[1356291]: DEBUG: [9dhthqb47rgqp8vg6elo]: [core] Destroying monologue 'apq2bhajd2' ()
Dec 30 09:17:47 slim rtpengine[1356291]: DEBUG: [9dhthqb47rgqp8vg6elo]: [core] Destroying monologue 'mitoh' (0)
Dec 30 09:17:47 slim rtpengine[1356291]: DEBUG: [9dhthqb47rgqp8vg6elo]: [core] Destroying monologue '' (1)
Dec 30 09:17:47 slim rtpengine[1356291]: DEBUG: [9dhthqb47rgqp8vg6elo]: [core] Destroying monologue '' (2)
Dec 30 09:17:47 slim rtpengine[1356291]: INFO: [9dhthqb47rgqp8vg6elo]: [core] Call branch 'apq2bhajd2' (via-branch '') deleted, no more branches remaining
I can't tell what exactly happened here since you didn't post the
actual signalling (just the result), but in general: Any branch
you create in rtpengine you also have to delete in the same way.
If you delete a branch based on the from-tag alone, then all
branches connected to that from-tag will be deleted (which I
suspect is what happened here). If you want to delete only one
branch, you need to use the appropriate via-branch (or to-tag if
there is one). Deleting branches is directional, so order of the
tags is important. Omitting the from-tag altogether would delete
the entire call, all tags, all branches.
Cheers
Here is the signalling. Opensips would have added the various tags and the "received from" address. The script only adds via-branch=extra which would the branch index. I remember this instance. The branch that didn't need rtpengine happened to be 0. I think that "Destroying monologue 'mitoh' (0)" is just rtpengine's order not the branch index that was passed. So the 0 here would have been branch index 1. The second branch but the first one requiring rtpengine. The point here is that there was no way of knowing that branch 0 did not have a relay dialogue associated with it.
xlog("checking for 487 status\n");
if (t_check_status("487")) {
xlog("A request was terminated, send delete for branch $T_branch_idx\n");
xlog("Branch is $T_branch_idx\n");
# rtpengine_delete(" via-branch=extra");
return;
That's the script doing the deletion, not the log of the signalling going to rtpengine. The log you posted below shows the call setup, not the call deletion. Also it looks different from your last email, which used branch tags "0", "1", and "2", while this one uses the actual branch tag from the Via header (although always the same one).
Using branch tags "0", "1", and "2" would be correct: different tags for different branches. The tags used in the answer and the deletions must match those tags. I don't know if this is the case since you didn't post it.
The log below shows the same branch tag used for all branches,
which is not correct. From rtpengine's point there were no
branches: it was simply a repeated offer going to the same
endpoint, but with different options. (This is similar to the
original issue you posted about, with the same branch tag used in
the reverse re-invite as in the original forward invite.)
(BTW, things would be a lot easier without constantly mixing
different issues and different scenarios.)
"ICE": "remove", "direction": [ "ipv6", "ipv4-priv" ], "flags": [ "debug" ], "replace": [ "session-connection", "origin" ], "transport-protocol": "RTP/AVP", "rtcp-mux": [ "demux" ], "call-id": "s25p40fpr5g0u52b96dp", "via-branch": "z9hG4bK3119290", "received-from": [ "IP6", "2001::F58F" ], "from-tag": "as1g4gcnjp", "command": "offer" }
"ICE": "remove", "direction": [ "ipv6", "ipv4-priv" ], "flags": [ "debug" ], "replace": [ "session-connection", "origin" ], "transport-protocol": "RTP/AVP", "rtcp-mux": [ "demux" ], "call-id": "s25p40fpr5g0u52b96dp", "via-branch": "z9hG4bK3119290", "received-from": [ "IP6", "2001::F58F" ], "from-tag": "as1g4gcnjp", "command": "offer" }
"ICE": "force", "DTLS-fingerprint": "sha-256", "direction": [ "ipv4-priv", "ipv4-ext" ], "flags": [ "debug", "SDES-off", "generate-mid" ], "replace": [ "session-connection", "origin" ], "transport-protocol": "UDP/TLS/RTP/SAVPF", "rtcp-mux": [ "require" ], "call-id": "s25p40fpr5g0u52b96dp", "via-branch": "z9hG4bK3119290", "received-from": [ "IP6", "2001::F58F" ], "from-tag": "as1g4gcnjp", "command": "offer" }
In this particular call "rtcp-mux" did not appear in the sdp presented to the caller which was a mandatory attribute. The call failed. Why did this happen? I assume because rtpengine stacked multiple rquirements on each other.
How can this work reliably with different requirements for different branches?
Correct. It works reliably by using the appropriate branch tags (again). This creates branches within rtpengine and each branch can have different options. To give a full example as it would appear in the log:
A → B offer: from-tag=A via-branch=1 ...other-options-for-B...
A → C offer: from-tag=A via-branch=2 ...other-options-for-C...
A → D offer: from-tag=A via-branch=3 ...other-options-for-D...
(Neither the from/to tags nor the branch tags have to be literal
"A" or "1" etc - those are just examples. They just need to be
unique, and matching between offers and answers/deletes.)
C answers:
C → A answer: from-tag=A via-branch=2 to-tag=C
...other-options...
delete B: from-tag=A via-branch=1 (optionally to-tag=B)
delete D: from-tag=A via-branch=3 (optionally to-tag=D)
(The deletes can also come before the answer.)
Hang-up:
Either delete from A's side: from-tag=A
or from C's side: from-tag=C
(This is assuming that B, C, D are actually distinct endpoints that receive the branched offers, possibly simultaneously. If they're actually the same endpoint and you're just retrying the offer with different options, you can leave the branching as it is now, but make sure you delete the call in between invocations with `delete-delay=0` to force a complete reset of the internal state. This would be a somewhat different use case than actual branching.)
Cheers