Janus SIP, WebRTC transfer

Hi,

Currently I use Janus with its (amazing) SIP plugin to bridge my PBX to WebRTC devices running my app. This works great, even over LTE connections. We use a coturn TURN server to relay RTP traffic.

Suppose that I want to “transfer” a WebRTC “call” to another WebRTC peer. I am not talking about a SIP transfer here, I am talking about a WebRTC “transfer”. I am aware of the fact that WebRTC does not implement such things by design; application and signalling layer have to be built by the developer.

Normally, in such a scenario, I would try to use ICE restart. I have tested this method without Janus (that is, two browsers calling each other, one browser “transfers” the call to another third browser using the ICE restart mechanism).

How would I approach such a scenario (WebRTC “transfers”) using the Janus SIP plugin. Is ICE restart a viable method? If so, how would that workout when Janus is the offerer (the PBX is being called)?

Maybe I am missing something completely, but I am stuck in the thought process. Any ideas on how to approach this particular scenario? Any help would be greatly appreciated.

Not sure what you mean by WebRTC transfer, but i suspect you’ll need a new PeerConnection.

1 Like

Hi Lorenzo,

Thanks for taking the time to look into my question. I have attached a schematic drawing to illustrate what I would like to achieve.

Setting up the green line (1) is no problem; this works fine (Smarthpone A initiates the call, he is the SDP offerer). Now suppose that during the call, the far end (i.e., extension 6001) wants to be transferred to speak with Smartphone B (the blue dashed line (2)).

A logical approach would be to create a new PeerConnection (as you suggested) on Smartphone B (this can be signalled through my proprietary protocol). How should I “inform” Janus that the local description has changed from Smartphone A to Smartphone B? (This is what I mean by “transferring”).

When reading the docs, one option looks viable: the “update” command of the SIP plugin. However, I cannot get this working with a simple browser and the janus.js file… After an ICE restart, the ICE connection goes to disconnected.

BTW, I use Janus v1.2.1 in this environment.

Since you’re already using SIP, looks like SIP transfer is what you should use.

Okay, maybe I have to rephrase the issue… I would like to focus on the ICE restart part, let’s forget about the “transfer” part.

The last few days I have been working on a working ICE transfer example. I have made a test setup where I use a browser to call a SIP extension using Janus and my PBX. I do not use trickle ICE and I have set the “iceTransportPolicy” set to relay (using my TURN server in the iceServers configuration of course). The call always works fine, I have bidirectional audio.

When I use the “iceRestart” parameter set to true when recreating my local SDP offer, I can see that the ufrag and pwd elements change, as well as the candidates (they have different port numbers). Then I use the SIP plugin’s “update” command to send my new offer in the JSEP, to force an ICE restart. In the Janus log, I see (as expected) “ICE restart detected”. I can see the re-invite to the PBX, the auto-accept… everything looks fine. I get the Janus “accepted” event with the new answer SDP.

However, when I set the new answer SDP using “setRemoteDescription()”, the following happens:

  1. Within 2 to 3 seconds, I see in my browser console that the ICE connection state goes to disconnected.
  2. I still have audio from the SIP extension to the browser for another 10 seconds or so, and then it completely stops.

I cannot seem to find the problem. Why does my ICE state change to disconnected when I perform an ICE restart with Janus? The initial call with the initial SDP always works. Could it be the PBX? Or have I made a mistake in understanding the “update” command?

Thanks again for your time; I appreciate your help!

You cannot use ICE to transfer a call somewhere else. DTLS will fail, as the new endpoint will try to set up a new DTLS handshake while the old one will assume the previous one will still apply.

Hi Lorenzo,

Thanks for your quick answer.

I no longer want to transfer a call somewhere else using ICE restart (you have made it clear that it isn’t a suitable method), but I am now focussing on why ICE restart itself does not seem to work.

In the example I described in my previous post, I restarted ICE from the same browser I generated the intial SDP from. This should work, right? Suppose I use a mobile app to make a call and I transition from Wi-Fi to 4G/5G/LTE, then we would need ICE restart to restart the ICE connection. That is exactly what I am trying to simulate in my simple browser setup.

From the logs and the admin-endpoint, I cannot explain why my audio breaks in both directions. I do not see any errors or warnings. One thing I noticed is that when I use pc.createOffer() with iceRestart set to true, I do not see an onselectedcandidatepairchange event happening, although I expect that to happen. Could that be an indicator that something is wrong?

I am sorry for my elaborate text, but I feel that providing context is necessary here.

An ICE restart should result in ICE credentials changing, so I’d start making sure that’s happening in the new SDPs.

I have checked the admin endpoint to extract the “local” and “remote” SDPs, both after establishing the call and after ICE restarting it from the browser. It seems that the ice-ufrag and the ice-pwd change, as expected. Janus also correctly detects an ICE restart when reading the logs.

These are the SDPs after establishing the call:

Local:
v=0
o=3cxPS 14351221406040064 8582151675052033 IN IP4 49.13.151.220
s=3cxPS Audio call
t=0 0
a=group:BUNDLE 0
a=ice-options:trickle
a=fingerprint:sha-256 35:AF:68:94:54:0F:94:03:67:CE:8E:90:FD:D7:29:AB:0F:FE:89:B8:66:73:40:55:00:95:EE:38:72:5D:F8:79
a=extmap-allow-mixed
a=msid-semantic: WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 111 9 0 8 110 126
c=IN IP4 49.13.151.220
a=sendrecv
a=mid:0
a=rtcp-mux
a=ice-ufrag:00jb
a=ice-pwd:nIHHhREEj53gFesaL84+DV
a=ice-options:trickle
a=setup:active
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
a=msid:janus janus0
a=ssrc:2554688321 cname:janus
a=candidate:1 1 udp 2015363327 172.20.0.4 45617 typ host
a=candidate:2 1 udp 1679819007 49.13.151.220 45617 typ srflx raddr 172.20.0.4 rport 45617
a=end-of-candidates

Remote:
v=0
o=- 4851837849663472097 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=extmap-allow-mixed
a=msid-semantic: WMS f2e0805e-0697-43a6-888f-afa6d1830a89
m=audio 49302 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
c=IN IP4 159.69.191.22
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2270475721 1 udp 16785407 159.69.191.22 49302 typ relay raddr 0.0.0.0 rport 0 generation 0 network-cost 999
a=candidate:2270475721 1 udp 16785407 159.69.191.22 54418 typ relay raddr 0.0.0.0 rport 0 generation 0 network-cost 999
a=ice-ufrag:LKxF
a=ice-pwd:pgQyC4rA+vVwddwwzbxEwq/G
a=ice-options:trickle
a=fingerprint:sha-256 38:E2:7D:DC:0F:68:29:96:9E:A8:9E:AF:FC:C8:79:DE:B1:50:D6:56:E4:B2:DE:7E:B0:ED:FD:5A:48:E7:C4:58
a=setup:actpass
a=mid:0
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=sendrecv
a=msid:f2e0805e-0697-43a6-888f-afa6d1830a89 84a07ef2-b4d9-439e-b884-d25b39051fb8
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
a=ssrc:3629667525 cname:LTC3tEx2i5axOSkC
a=ssrc:3629667525 msid:f2e0805e-0697-43a6-888f-afa6d1830a89 84a07ef2-b4d9-439e-b884-d25b39051fb8

And these are the SDPs after ICE restarting the call from the browser:

Local:
v=0
o=3cxPS 14351221406040064 8582151675052034 IN IP4 49.13.151.220
s=3cxPS Audio call
t=0 0
a=group:BUNDLE 0
a=ice-options:trickle
a=fingerprint:sha-256 35:AF:68:94:54:0F:94:03:67:CE:8E:90:FD:D7:29:AB:0F:FE:89:B8:66:73:40:55:00:95:EE:38:72:5D:F8:79
a=extmap-allow-mixed
a=msid-semantic: WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 111 9 0 8 110 126
c=IN IP4 49.13.151.220
a=sendrecv
a=mid:0
a=rtcp-mux
a=ice-ufrag:jw54
a=ice-pwd:0xLNZtVC6NmFhj1gdOk8rN
a=ice-options:trickle
a=setup:active
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
a=msid:janus janus0
a=ssrc:2554688321 cname:janus
a=candidate:1 1 udp 2015363327 172.20.0.4 45617 typ host
a=candidate:2 1 udp 1679819007 49.13.151.220 45617 typ srflx raddr 172.20.0.4 rport 45617
a=end-of-candidates

Remote:
v=0
o=- 4851837849663472097 3 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=extmap-allow-mixed
a=msid-semantic: WMS f2e0805e-0697-43a6-888f-afa6d1830a89
m=audio 59844 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
c=IN IP4 159.69.191.22
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2270475721 1 udp 16785407 159.69.191.22 59844 typ relay raddr 0.0.0.0 rport 0 generation 1 network-cost 999
a=candidate:2270475721 1 udp 16785407 159.69.191.22 58972 typ relay raddr 0.0.0.0 rport 0 generation 1 network-cost 999
a=ice-ufrag:jjaa
a=ice-pwd:Nubrry8jOnVk2c8tlwrQlw+d
a=ice-options:trickle
a=fingerprint:sha-256 38:E2:7D:DC:0F:68:29:96:9E:A8:9E:AF:FC:C8:79:DE:B1:50:D6:56:E4:B2:DE:7E:B0:ED:FD:5A:48:E7:C4:58
a=setup:actpass
a=mid:0
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=sendrecv
a=msid:f2e0805e-0697-43a6-888f-afa6d1830a89 84a07ef2-b4d9-439e-b884-d25b39051fb8
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
a=ssrc:3629667525 cname:LTC3tEx2i5axOSkC
a=ssrc:3629667525 msid:f2e0805e-0697-43a6-888f-afa6d1830a89 84a07ef2-b4d9-439e-b884-d25b39051fb8