在尝试使用Objective C API建立WebRTC数据通道时,我无法实际捕获任何RTCDataChannelDelegate回调。关于对等连接,一切似乎都很顺利,但我只到了成功添加对等连接流的地步。
我的步骤大致如下:
创建报价:
_channel = [_connection createDataChannelWithLabel: @"offer-1"
config: [[RTCDataChannelInit alloc] init]];
_channel.delegate = _stateMachine;
[_connection createOfferWithDelegate: _stateMachine constraints: [[RTCMediaConstraints alloc] init]];
客户端1的SDP被发送到客户端2,在那里创建一个答案:
[_connection setRemoteDescriptionWithDelegate: _stateMachine sessionDescription: [[RTCSessionDescription alloc] initWithType: @"offer" sdp: sdp]];
[_connection createAnswerWithDelegate: _stateMachine constraints: [[RTCMediaConstraints alloc] init]];
客户端2的SDP被发送回客户端1:
[_connection setRemoteDescriptionWithDelegate: _stateMachine sessionDescription: [[RTCSessionDescription alloc] initWithType: @"answer" sdp: sdp]];
在那之后,我得到了添加了信号稳定的媒体流。以前,在我的POC期间,我能够获得数据通道回调,但我不太确定我在这里缺少了什么。
以下是对等连接设置:
RTCPeerConnectionFactory* _cfactory = [[RTCPeerConnectionFactory alloc] init];
NSArray* mandatory = @[
[[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"],
[[RTCPair alloc] initWithKey:@"internalSctpDataChannels" value:@"true"],
];
RTCMediaConstraints* pcConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints: mandatory
optionalConstraints: nil];
RTCICEServer* server = [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:@"stun:stun.l.google.com:19302"]
username: @""
password: @""];
NSArray* servers = @[server];
_connection = [_cfactory peerConnectionWithICEServers: servers
constraints: pcConstraints
delegate: _stateMachine];
我的状态机在所有方法都存在的情况下实现以下内容:
@protocol DelegateAggregator
<RTCPeerConnectionDelegate, RTCSessionDescriptionDelegate, RTCDataChannelDelegate, RTCStatsDelegate>
@end
我这里缺什么了吗?频道似乎正在建立,并添加了媒体流(我只想要数据),但没有任何回调。我可以启用更多日志记录吗?任何帮助都将不胜感激!
因此,我构建答案的关键错误是在向客户端1发送SDP的回调中。我正在等待会话创建的对委托的回调,以将我的回答发送回客户端1。事实证明,现在还为时过早,候选人聚会还没有结束。我在代理中设置了回调,看起来像这样:
//WRONG
_tunnel.stateMachine.peerConnectionSessionCallback = ^(RTCPeerConnection* peerConnection, RTCSessionDescription* sdp, NSError* error) {
SessionAnswer* answer = [[SessionAnswer alloc] init];
answer.sdp = [sdp description];
[queueManager sendEvent: answer];
};
正确的方法是等待此事件:
_tunnel.stateMachine.peerConnectionICEGatheringCallback = ^(RTCPeerConnection* peerConnection, RTCICEGatheringState newState) {
if (newState == RTCICEGatheringComplete) {
SessionAnswer* answer = [[SessionAnswer alloc] init];
answer.sdp = [[peerConnection localDescription] description];
[queueManager sendEvent: answer];
}
};
一旦我以这种方式构建它,数据通道回调就会像预期的那样启动。
DtlsSrtpKeyAgreement
和internalSctpDataChannels
需要放入可选约束,而不是强制约束。
为了设置数据通道,我还将RtpDataChannels
设置为可选。