DataChannel Webrtc IOS

1,300 views
Skip to first unread message

Dustin

unread,
Mar 14, 2017, 10:24:22 AM3/14/17
to discuss-webrtc

I want to create an data channel. But I'm having some difficulties to implement this. I have added the code that runs on the "caller side":

func initWebRTC() {
        RTCInitializeSSL()
        peerConnectionFactory = RTCPeerConnectionFactory()

        let mandatoryConstraints = ["OfferToReceiveAudio": "true", "OfferToReceiveVideo": "false"]
        let optionalConstraints = [ "DtlsSrtpKeyAgreement": "true", "RtpDataChannels" : "true"]


        mediaConstraints = RTCMediaConstraints.init(mandatoryConstraints: mandatoryConstraints, optionalConstraints: optionalConstraints)
    }

func prepareNewConnection() -> RTCPeerConnection {
        var icsServers: [RTCIceServer] = []

        icsServers.append(RTCIceServer(urlStrings: ["stun:stun.l.google.com:19302"], username:"",credential: ""))

        let rtcConfig: RTCConfiguration = RTCConfiguration()
        rtcConfig.tcpCandidatePolicy = RTCTcpCandidatePolicy.disabled
        rtcConfig.bundlePolicy = RTCBundlePolicy.maxBundle
        rtcConfig.rtcpMuxPolicy = RTCRtcpMuxPolicy.require
        rtcConfig.iceServers = icsServers;

        peerConnection = peerConnectionFactory.peerConnection(with: rtcConfig, constraints: mediaConstraints, delegate: self)
        peerConnection.add(mediaStream);

        let tt = RTCDataChannelConfiguration();
        tt.isOrdered = false;

        tt.isNegotiated = false

        self.dataChannel = peerConnection.dataChannel(forLabel: "datachannel", configuration: tt)

        self.dataChannel.delegate = self
        print("create datachannel")

        return peerConnection;
    }

I create the data channel before the offer as said by many people. This method (see next code) is called several times. The channel state is going from 2 to 3. 

public func dataChannelDidChangeState(_ dataChannel: RTCDataChannel){
        print("channel.state \(dataChannel.readyState.rawValue)");
    }

But what do I need to do at the receiving side? Because nothing happens there? Do I need to bind the data channel to the receiver side? If so, how can I do that?

Taylor Brandstetter

unread,
Mar 14, 2017, 5:46:15 PM3/14/17
to discuss-webrtc
For data channels negotiated in-band (as in your case), you can wait for the didOpenDataChannel callback on the remote side.

Or, you can negotiate the data channel out of band by creating a channel on both sides, and setting the channelId field of RTCDataChannelConfiguration to the same value.

--

---
You received this message because you are subscribed to the Google Groups "discuss-webrtc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrtc+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/discuss-webrtc/49256f78-032b-4098-8626-186c7d4a82bb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dustin

unread,
Mar 29, 2017, 5:35:15 PM3/29/17
to discuss-webrtc
I get you answer, but this doesn't seem to work. The ice connection state on the client is .connected, en any moment later .completed. On the receiver side it stays at .connected. However, the didOpen data channel is never called. 

The dataChannelDidChangeState method is called. It is called before the ice connection is connected or completed. The data channel state is going from .closing to .closed. 


Op dinsdag 14 maart 2017 22:46:15 UTC+1 schreef Taylor Brandstetter:
To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrt...@googlegroups.com.

Taylor Brandstetter

unread,
Mar 29, 2017, 5:44:56 PM3/29/17
to discuss-webrtc
I just noticed you're setting an "RtpDataChannels" constraint. RTP data channels aren't officially supported any more; can you remove this, in order to use SCTP?

To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrtc+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/discuss-webrtc/ff11a4ce-069b-493b-ad3c-472cff79a98c%40googlegroups.com.

Dustin

unread,
Mar 30, 2017, 1:59:44 PM3/30/17
to discuss-webrtc
Ah, thank you! It works. I get the didOpenDatachannel on the remote side,  but what do I need to do there? Do I need to set an delegate, and save the current data channel or is that handled by webrtc?

Op woensdag 29 maart 2017 23:44:56 UTC+2 schreef Taylor Brandstetter:

Taylor Brandstetter

unread,
Mar 30, 2017, 2:25:11 PM3/30/17
to discuss-webrtc
Yes; you should set a delegate and store a reference to the data channel from that callback, since there's no way to get access to it afterwards (as I recall).

Or, as a briefly mentioned before, you could negotiate the data channel "out-of-band", by creating a data channel on both sides, setting "isNegotiated" to true and setting "channelId" to the same value. Then you wouldn't need to use "didOpenDatachannel", you'd just need to wait for the state to change to "open".

To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrtc+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/discuss-webrtc/628bc7e6-f5c9-42af-aca1-5787f7287a3b%40googlegroups.com.

Dustin

unread,
Mar 30, 2017, 5:00:28 PM3/30/17
to discuss-webrtc
I have managed to get it working properly. Thanks for your time and help!

Op donderdag 30 maart 2017 20:25:11 UTC+2 schreef Taylor Brandstetter:

Archer Chen

unread,
May 3, 2017, 11:40:16 PM5/3/17
to discuss-webrtc
Chrome myrtclib.js:
    var pc_constraints = {"optional": [{RtpDataChannels: true}]};
    var data_constraint = {reliable :false};


    function doCall() {
       createDataChannel("caller");
       pc.createOffer(setLocalAndSendMessage, failureCallback, null);
    };

    function createDataChannel(role) {
        try {
            sendDChannel = pc.createDataChannel("datachannel_"+room+role, data_constraint);
        } catch (e) {
            console.log('error creating data channel ' + e);
            return;
        }
        sendDChannel.onopen = onSendChannelStateChange;
        sendDChannel.onclose = onSendChannelStateChange;
    }

When the dataChannel is created, I see the channel id of dataChannel is 65535

- (RTCConfiguration *)peerConnectionConfiguration

{

    RTCConfiguration * configuration = [[RTCConfiguration alloc] init];

    

    if (!mICEServers)

    {

        mICEServers = [NSMutableArray array];

        NSArray * iceServers = @[RTCSTUNServerURL];  //RTCSTUNServerURL: @"stun:stun.l.google.com:19302"

        [mICEServers addObject:[self defaultSTUNServer:iceServers]];   

    }

    

    configuration.iceServers = mICEServers;

    

    return configuration;

}


- (RTCMediaConstraints *)peerConnectionMediaConstraints

{

    return [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil optionalConstraints:nil];

}

- (RTCPeerConnection *)createPeerConnectionWithDataChannelLabel:(NSString *)connectionId

{

    RTCConfiguration * configuration = [self peerConnectionConfiguration];

    RTCMediaConstraints * mediaConstraints = [self peerConnectionMediaConstraints];

    

    RTCPeerConnection * peerConnection = [mPeerFactory peerConnectionWithConfiguration:configuration constraints:mediaConstraints delegate:self];

    

    if (peerConnection)

    {

        NSLog(@"Create peer connection successfully for %@", connectionId);

        

        RTCDataChannelConfiguration * dataChannelConfiguration = [[RTCDataChannelConfiguration alloc] init];

//        dataChannelConfiguration.channelId = 65535;

//        dataChannelConfiguration.isNegotiated = YES;

        // connectionId : datachannel_+room+role 

        RTCDataChannel *dataChannel = [peerConnection dataChannelForLabel:connectionId configuration:dataChannelConfiguration];

        

        if (dataChannel)

        {

            dataChannel.delegate = self;

            

            NSLog(@"Data channel status : %@", [dataChannel readyStatus]);

        }

        else

        {

            NSLog(@"Create data channel failed for %@", connectionId);

        }

    }

    else

    {

        NSLog(@"Create peer connection failed for %@", connectionId);

    }

    

    return peerConnection;

}


issue:
1. If I set channelId, it will crash
2. If I set isNegotiated, `peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection` is called.

The most important issue: 
The dataChannel can not open?

So, if someone can help me?

My mac: 10.12.4
xcode : 8.3.2

WebRTC framework verson: M58
git status
HEAD detached at 4e72b0f87

if need web, I will provide.

在 2017年3月14日星期二 UTC+8下午10:24:22,Dustin写道:
在 2017年3月14日星期二 UTC+8下午10:24:22,Dustin写道:

Archer Chen

unread,
May 3, 2017, 11:43:26 PM5/3/17
to discuss-webrtc
Now, if it must not set up "RtpDataChannels". Now, I can not create data channel successfully.

在 2017年3月30日星期四 UTC+8上午5:44:56,Taylor Brandstetter写道:
Reply all
Reply to author
Forward
0 new messages