sipsorcery-org / sipsorcery

A WebRTC, SIP and VoIP library for C# and .NET. Designed for real-time communications apps.
https://sipsorcery-org.github.io/sipsorcery
Other
1.43k stars 432 forks source link

Question: SS and the WebRTC "perfect negotiation" #527

Open dc-ucw opened 3 years ago

dc-ucw commented 3 years ago

Hi Aaron, thanks for such a great library and contributing to open source.

I am new to WebRTC and trying to implement the WebRTC "Perfect Negotiation" pattern: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Perfect_negotiation

I have succeeded doing this between two javascript/browser peers, and I am now trying to do it with a javascript/browser to SipSorcery c# peer. I notice that SS does not have the WebRTC method a rtcPeerConnection.setLocalDescription() method. So I started to look harder at your WebRTCReceive example, and noticed that the javascript peer (capture.html) has code to receive an offer and send an answer, but the SS peer (Program.cs) has no code for offer/answer. I am confused how the two "know" what media is being sent and the media formats.

I also notice no negotiation for ICE candidates as well.

thanks for the help dc

sipsorcery commented 3 years ago

Hi dc,

I notice that SS does not have the WebRTC method a rtcPeerConnection.setLocalDescription() method

It does, here.

but the SS peer (Program.cs) has no code for offer/answer. I am confused how the two "know" what media is being sent and the media formats. I also notice no negotiation for ICE candidates as well.

The sipsorcery can act in either the offer or answer role and can also exchange ICE candidates. For the majority of the RTCPeerConnection javascript calls there should be the exact same, over very close, call on the RTCPeerConnection class in this library.

For most of the examples the sipsorcery library acts as the offerer and skips the signalling to exchange ICE candidates. This is to keep the signalling logic as small as possible. The sipsorcery library can act as the answerer and handle the addition of remote ICE candidates but it takes extra wiring to coordinate. That extra wiring is the signalling and is not part of the WebRTC specification. If you're using some kind of signalling server between your javascript WebRTC peers you should be able to use the exact same calls with the sipsorcery library.

dc-ucw commented 3 years ago

Hi Aaron, thanks for the quick reply. My apologies, I do now see setLocalDescription, which requires a parameter.

Do you have support for "Implicit Description" or any way I can do it as it is described in the WebRTC API? In Javascript this is done by calling setLocalDescription() with no parameters. Here are the details: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription

dc

sipsorcery commented 3 years ago

Do you have support for "Implicit Description" or any way I can do it as it is described in the WebRTC API?

No, not yet. It's on the list. I might even try and do it today.

I think that call changed from when I started on the WebRTC spec. Either that or I just misread something. For the time being you'll need to make two calls.

dc-ucw commented 3 years ago

Thanks Aaron, much appreciated. Here is the code I used to implement implicit description. Its based on another post I read about node.js at https://github.com/node-webrtc/node-webrtc/issues/677 Take it with a grain of salt, it "appears" to work.

private static Task setImplicitDescription(RTCPeerConnection rtcPeerConnection)
        {
            if (rtcPeerConnection.signalingState == RTCSignalingState.stable ||
                rtcPeerConnection.signalingState == RTCSignalingState.have_local_offer ||
                rtcPeerConnection.signalingState == RTCSignalingState.have_local_pranswer)
            {
                var sdp = rtcPeerConnection.createOffer();
                var init = new RTCSessionDescriptionInit();
                init.type = RTCSdpType.offer;
                init.sdp = sdp.ToString();

                rtcPeerConnection.setLocalDescription(init);
            } 
            else
            {
                var init = rtcPeerConnection.createAnswer();
                rtcPeerConnection.setLocalDescription(init);
            }

            return Task.CompletedTask;
        }
rafcsoares commented 3 years ago

@sipsorcery I committed today an initial version with support for this feature.