blob: ebdd12033ff6f3be7bc14e0ade20e29fd72d821e [file] [log] [blame]
hjonf396f602016-02-11 16:19:06 -08001/*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
tkchin9eeb6242016-04-27 01:54:20 -070011#import "RTCPeerConnection+Private.h"
12
tkchin9eeb6242016-04-27 01:54:20 -070013#import "RTCConfiguration+Private.h"
14#import "RTCDataChannel+Private.h"
15#import "RTCIceCandidate+Private.h"
hbosbd3dda62016-09-09 01:36:28 -070016#import "RTCLegacyStatsReport+Private.h"
tkchin9eeb6242016-04-27 01:54:20 -070017#import "RTCMediaConstraints+Private.h"
18#import "RTCMediaStream+Private.h"
Steve Anton8cb344a2018-02-27 15:34:53 -080019#import "RTCMediaStreamTrack+Private.h"
tkchin9eeb6242016-04-27 01:54:20 -070020#import "RTCPeerConnectionFactory+Private.h"
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -070021#import "RTCRtpReceiver+Private.h"
tkchin9eeb6242016-04-27 01:54:20 -070022#import "RTCRtpSender+Private.h"
Steve Anton8cb344a2018-02-27 15:34:53 -080023#import "RTCRtpTransceiver+Private.h"
tkchin9eeb6242016-04-27 01:54:20 -070024#import "RTCSessionDescription+Private.h"
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020025#import "base/RTCLogging.h"
26#import "helpers/NSString+StdString.h"
hjonf396f602016-02-11 16:19:06 -080027
kwibergbfefb032016-05-01 14:53:46 -070028#include <memory>
29
Steve Anton10542f22019-01-11 09:11:00 -080030#include "api/jsep_ice_candidate.h"
Niels Möller695cf6a2019-05-13 12:27:23 +020031#include "api/rtc_event_log_output_file.h"
Niels Möller65f17ca2019-09-12 13:59:36 +020032#include "api/transport/media/media_transport_interface.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020033#include "rtc_base/checks.h"
Niels Möller695cf6a2019-05-13 12:27:23 +020034#include "rtc_base/numerics/safe_conversions.h"
hjonf396f602016-02-11 16:19:06 -080035
hjonf396f602016-02-11 16:19:06 -080036NSString * const kRTCPeerConnectionErrorDomain =
37 @"org.webrtc.RTCPeerConnection";
38int const kRTCPeerConnnectionSessionDescriptionError = -1;
39
40namespace webrtc {
41
42class CreateSessionDescriptionObserverAdapter
43 : public CreateSessionDescriptionObserver {
44 public:
45 CreateSessionDescriptionObserverAdapter(
46 void (^completionHandler)(RTCSessionDescription *sessionDescription,
47 NSError *error)) {
48 completion_handler_ = completionHandler;
49 }
50
Mirko Bonadei17aff352018-07-26 12:20:40 +020051 ~CreateSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
hjonf396f602016-02-11 16:19:06 -080052
53 void OnSuccess(SessionDescriptionInterface *desc) override {
54 RTC_DCHECK(completion_handler_);
kwibergbfefb032016-05-01 14:53:46 -070055 std::unique_ptr<webrtc::SessionDescriptionInterface> description =
56 std::unique_ptr<webrtc::SessionDescriptionInterface>(desc);
hjonf396f602016-02-11 16:19:06 -080057 RTCSessionDescription* session =
58 [[RTCSessionDescription alloc] initWithNativeDescription:
59 description.get()];
60 completion_handler_(session, nil);
61 completion_handler_ = nil;
62 }
63
Harald Alvestrand73771a82018-05-24 10:53:49 +020064 void OnFailure(RTCError error) override {
hjonf396f602016-02-11 16:19:06 -080065 RTC_DCHECK(completion_handler_);
Harald Alvestrand73771a82018-05-24 10:53:49 +020066 // TODO(hta): Add handling of error.type()
67 NSString *str = [NSString stringForStdString:error.message()];
hjonf396f602016-02-11 16:19:06 -080068 NSError* err =
69 [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
70 code:kRTCPeerConnnectionSessionDescriptionError
71 userInfo:@{ NSLocalizedDescriptionKey : str }];
72 completion_handler_(nil, err);
73 completion_handler_ = nil;
74 }
75
76 private:
77 void (^completion_handler_)
78 (RTCSessionDescription *sessionDescription, NSError *error);
79};
80
81class SetSessionDescriptionObserverAdapter :
82 public SetSessionDescriptionObserver {
83 public:
84 SetSessionDescriptionObserverAdapter(void (^completionHandler)
85 (NSError *error)) {
86 completion_handler_ = completionHandler;
87 }
88
Mirko Bonadei17aff352018-07-26 12:20:40 +020089 ~SetSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
hjonf396f602016-02-11 16:19:06 -080090
91 void OnSuccess() override {
92 RTC_DCHECK(completion_handler_);
93 completion_handler_(nil);
94 completion_handler_ = nil;
95 }
96
Harald Alvestrand73771a82018-05-24 10:53:49 +020097 void OnFailure(RTCError error) override {
hjonf396f602016-02-11 16:19:06 -080098 RTC_DCHECK(completion_handler_);
Harald Alvestrand73771a82018-05-24 10:53:49 +020099 // TODO(hta): Add handling of error.type()
100 NSString *str = [NSString stringForStdString:error.message()];
hjonf396f602016-02-11 16:19:06 -0800101 NSError* err =
102 [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
103 code:kRTCPeerConnnectionSessionDescriptionError
104 userInfo:@{ NSLocalizedDescriptionKey : str }];
105 completion_handler_(err);
106 completion_handler_ = nil;
107 }
108
109 private:
110 void (^completion_handler_)(NSError *error);
111};
112
113PeerConnectionDelegateAdapter::PeerConnectionDelegateAdapter(
114 RTCPeerConnection *peerConnection) {
115 peer_connection_ = peerConnection;
116}
117
118PeerConnectionDelegateAdapter::~PeerConnectionDelegateAdapter() {
119 peer_connection_ = nil;
120}
121
122void PeerConnectionDelegateAdapter::OnSignalingChange(
123 PeerConnectionInterface::SignalingState new_state) {
124 RTCSignalingState state =
125 [[RTCPeerConnection class] signalingStateForNativeState:new_state];
126 RTCPeerConnection *peer_connection = peer_connection_;
127 [peer_connection.delegate peerConnection:peer_connection
128 didChangeSignalingState:state];
129}
130
131void PeerConnectionDelegateAdapter::OnAddStream(
deadbeefd5f41ce2016-06-08 13:31:45 -0700132 rtc::scoped_refptr<MediaStreamInterface> stream) {
hjonf396f602016-02-11 16:19:06 -0800133 RTCPeerConnection *peer_connection = peer_connection_;
Yura Yaroshevichc806c1d2018-06-21 12:51:11 +0300134 RTCMediaStream *mediaStream =
135 [[RTCMediaStream alloc] initWithFactory:peer_connection.factory nativeMediaStream:stream];
hjonf396f602016-02-11 16:19:06 -0800136 [peer_connection.delegate peerConnection:peer_connection
137 didAddStream:mediaStream];
138}
139
140void PeerConnectionDelegateAdapter::OnRemoveStream(
deadbeefd5f41ce2016-06-08 13:31:45 -0700141 rtc::scoped_refptr<MediaStreamInterface> stream) {
hjonf396f602016-02-11 16:19:06 -0800142 RTCPeerConnection *peer_connection = peer_connection_;
Yura Yaroshevichc806c1d2018-06-21 12:51:11 +0300143 RTCMediaStream *mediaStream =
144 [[RTCMediaStream alloc] initWithFactory:peer_connection.factory nativeMediaStream:stream];
145
hjonf396f602016-02-11 16:19:06 -0800146 [peer_connection.delegate peerConnection:peer_connection
147 didRemoveStream:mediaStream];
148}
149
Steve Anton8cb344a2018-02-27 15:34:53 -0800150void PeerConnectionDelegateAdapter::OnTrack(
151 rtc::scoped_refptr<RtpTransceiverInterface> nativeTransceiver) {
Steve Anton8cb344a2018-02-27 15:34:53 -0800152 RTCPeerConnection *peer_connection = peer_connection_;
Yura Yaroshevich08f14dd2018-07-09 11:56:06 +0300153 RTCRtpTransceiver *transceiver =
154 [[RTCRtpTransceiver alloc] initWithFactory:peer_connection.factory
155 nativeRtpTransceiver:nativeTransceiver];
Steve Anton8cb344a2018-02-27 15:34:53 -0800156 if ([peer_connection.delegate
157 respondsToSelector:@selector(peerConnection:didStartReceivingOnTransceiver:)]) {
158 [peer_connection.delegate peerConnection:peer_connection
159 didStartReceivingOnTransceiver:transceiver];
160 }
161}
162
hjonf396f602016-02-11 16:19:06 -0800163void PeerConnectionDelegateAdapter::OnDataChannel(
deadbeefd5f41ce2016-06-08 13:31:45 -0700164 rtc::scoped_refptr<DataChannelInterface> data_channel) {
hjonf396f602016-02-11 16:19:06 -0800165 RTCPeerConnection *peer_connection = peer_connection_;
Yura Yaroshevichc75b35a2018-06-27 17:09:14 +0300166 RTCDataChannel *dataChannel = [[RTCDataChannel alloc] initWithFactory:peer_connection.factory
167 nativeDataChannel:data_channel];
hjonf396f602016-02-11 16:19:06 -0800168 [peer_connection.delegate peerConnection:peer_connection
169 didOpenDataChannel:dataChannel];
170}
171
172void PeerConnectionDelegateAdapter::OnRenegotiationNeeded() {
173 RTCPeerConnection *peer_connection = peer_connection_;
174 [peer_connection.delegate peerConnectionShouldNegotiate:peer_connection];
175}
176
177void PeerConnectionDelegateAdapter::OnIceConnectionChange(
178 PeerConnectionInterface::IceConnectionState new_state) {
Jonas Olssoncfddbb72018-11-15 16:52:45 +0100179 RTCIceConnectionState state = [RTCPeerConnection iceConnectionStateForNativeState:new_state];
180 [peer_connection_.delegate peerConnection:peer_connection_ didChangeIceConnectionState:state];
181}
182
Qingsi Wang36e31472019-05-29 11:37:26 -0700183void PeerConnectionDelegateAdapter::OnStandardizedIceConnectionChange(
184 PeerConnectionInterface::IceConnectionState new_state) {
185 if ([peer_connection_.delegate
186 respondsToSelector:@selector(peerConnection:didChangeStandardizedIceConnectionState:)]) {
187 RTCIceConnectionState state = [RTCPeerConnection iceConnectionStateForNativeState:new_state];
188 [peer_connection_.delegate peerConnection:peer_connection_
189 didChangeStandardizedIceConnectionState:state];
190 }
191}
192
Jonas Olssoncfddbb72018-11-15 16:52:45 +0100193void PeerConnectionDelegateAdapter::OnConnectionChange(
194 PeerConnectionInterface::PeerConnectionState new_state) {
195 if ([peer_connection_.delegate
196 respondsToSelector:@selector(peerConnection:didChangeConnectionState:)]) {
197 RTCPeerConnectionState state = [RTCPeerConnection connectionStateForNativeState:new_state];
198 [peer_connection_.delegate peerConnection:peer_connection_ didChangeConnectionState:state];
199 }
hjonf396f602016-02-11 16:19:06 -0800200}
201
202void PeerConnectionDelegateAdapter::OnIceGatheringChange(
203 PeerConnectionInterface::IceGatheringState new_state) {
204 RTCIceGatheringState state =
205 [[RTCPeerConnection class] iceGatheringStateForNativeState:new_state];
206 RTCPeerConnection *peer_connection = peer_connection_;
207 [peer_connection.delegate peerConnection:peer_connection
208 didChangeIceGatheringState:state];
209}
210
211void PeerConnectionDelegateAdapter::OnIceCandidate(
212 const IceCandidateInterface *candidate) {
213 RTCIceCandidate *iceCandidate =
214 [[RTCIceCandidate alloc] initWithNativeCandidate:candidate];
215 RTCPeerConnection *peer_connection = peer_connection_;
216 [peer_connection.delegate peerConnection:peer_connection
217 didGenerateIceCandidate:iceCandidate];
218}
Honghai Zhangda2ba4d2016-05-23 11:53:14 -0700219
220void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
221 const std::vector<cricket::Candidate>& candidates) {
222 NSMutableArray* ice_candidates =
223 [NSMutableArray arrayWithCapacity:candidates.size()];
224 for (const auto& candidate : candidates) {
225 std::unique_ptr<JsepIceCandidate> candidate_wrapper(
226 new JsepIceCandidate(candidate.transport_name(), -1, candidate));
227 RTCIceCandidate* ice_candidate = [[RTCIceCandidate alloc]
228 initWithNativeCandidate:candidate_wrapper.get()];
229 [ice_candidates addObject:ice_candidate];
230 }
231 RTCPeerConnection* peer_connection = peer_connection_;
232 [peer_connection.delegate peerConnection:peer_connection
233 didRemoveIceCandidates:ice_candidates];
234}
235
Alex Drake43faee02019-08-12 16:27:34 -0700236void PeerConnectionDelegateAdapter::OnIceSelectedCandidatePairChanged(
237 const cricket::CandidatePairChangeEvent &event) {
Qingsi Wang7cdcda92019-08-28 09:18:37 -0700238 const auto &selected_pair = event.selected_candidate_pair;
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200239 auto local_candidate_wrapper = std::make_unique<JsepIceCandidate>(
Qingsi Wang7cdcda92019-08-28 09:18:37 -0700240 selected_pair.local_candidate().transport_name(), -1, selected_pair.local_candidate());
Alex Drake43faee02019-08-12 16:27:34 -0700241 RTCIceCandidate *local_candidate =
Qingsi Wang7cdcda92019-08-28 09:18:37 -0700242 [[RTCIceCandidate alloc] initWithNativeCandidate:local_candidate_wrapper.release()];
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200243 auto remote_candidate_wrapper = std::make_unique<JsepIceCandidate>(
Qingsi Wang7cdcda92019-08-28 09:18:37 -0700244 selected_pair.remote_candidate().transport_name(), -1, selected_pair.remote_candidate());
Alex Drake43faee02019-08-12 16:27:34 -0700245 RTCIceCandidate *remote_candidate =
Qingsi Wang7cdcda92019-08-28 09:18:37 -0700246 [[RTCIceCandidate alloc] initWithNativeCandidate:remote_candidate_wrapper.release()];
Alex Drake43faee02019-08-12 16:27:34 -0700247 RTCPeerConnection *peer_connection = peer_connection_;
248 NSString *nsstr_reason = [NSString stringForStdString:event.reason];
249 if ([peer_connection.delegate
250 respondsToSelector:@selector
251 (peerConnection:didChangeLocalCandidate:remoteCandidate:lastReceivedMs:changeReason:)]) {
252 [peer_connection.delegate peerConnection:peer_connection
253 didChangeLocalCandidate:local_candidate
254 remoteCandidate:remote_candidate
255 lastReceivedMs:event.last_data_received_ms
256 changeReason:nsstr_reason];
257 }
258}
259
Yura Yaroshevich546d7f92018-02-28 21:06:34 +0300260void PeerConnectionDelegateAdapter::OnAddTrack(
261 rtc::scoped_refptr<RtpReceiverInterface> receiver,
Alex Drake43faee02019-08-12 16:27:34 -0700262 const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) {
Yura Yaroshevich546d7f92018-02-28 21:06:34 +0300263 RTCPeerConnection *peer_connection = peer_connection_;
Alex Drake43faee02019-08-12 16:27:34 -0700264 if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:
265 didAddReceiver:streams:)]) {
Yura Yaroshevich546d7f92018-02-28 21:06:34 +0300266 NSMutableArray *mediaStreams = [NSMutableArray arrayWithCapacity:streams.size()];
Alex Drake43faee02019-08-12 16:27:34 -0700267 for (const auto &nativeStream : streams) {
Yura Yaroshevichc806c1d2018-06-21 12:51:11 +0300268 RTCMediaStream *mediaStream = [[RTCMediaStream alloc] initWithFactory:peer_connection.factory
269 nativeMediaStream:nativeStream];
Yura Yaroshevich546d7f92018-02-28 21:06:34 +0300270 [mediaStreams addObject:mediaStream];
271 }
Alex Drake43faee02019-08-12 16:27:34 -0700272 RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory
273 nativeRtpReceiver:receiver];
Yura Yaroshevich546d7f92018-02-28 21:06:34 +0300274
275 [peer_connection.delegate peerConnection:peer_connection
276 didAddReceiver:rtpReceiver
277 streams:mediaStreams];
278 }
279}
280
Zeke Chin8de502b2018-08-21 11:41:07 -0700281void PeerConnectionDelegateAdapter::OnRemoveTrack(
282 rtc::scoped_refptr<RtpReceiverInterface> receiver) {
283 RTCPeerConnection *peer_connection = peer_connection_;
284 if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:didRemoveReceiver:)]) {
Alex Drake43faee02019-08-12 16:27:34 -0700285 RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory
286 nativeRtpReceiver:receiver];
Zeke Chin8de502b2018-08-21 11:41:07 -0700287 [peer_connection.delegate peerConnection:peer_connection didRemoveReceiver:rtpReceiver];
288 }
289}
290
hjonf396f602016-02-11 16:19:06 -0800291} // namespace webrtc
292
hjonf396f602016-02-11 16:19:06 -0800293@implementation RTCPeerConnection {
Yura Yaroshevich5297bd22018-06-19 12:51:51 +0300294 RTCPeerConnectionFactory *_factory;
vopatop.skam96b6b832016-08-18 14:21:20 -0700295 NSMutableArray<RTCMediaStream *> *_localStreams;
kwibergbfefb032016-05-01 14:53:46 -0700296 std::unique_ptr<webrtc::PeerConnectionDelegateAdapter> _observer;
hjonf396f602016-02-11 16:19:06 -0800297 rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
deadbeef5d0b6d82017-01-09 16:05:28 -0800298 std::unique_ptr<webrtc::MediaConstraints> _nativeConstraints;
ivoc14d5dbe2016-07-04 07:06:55 -0700299 BOOL _hasStartedRtcEventLog;
hjonf396f602016-02-11 16:19:06 -0800300}
301
302@synthesize delegate = _delegate;
Yura Yaroshevichc806c1d2018-06-21 12:51:11 +0300303@synthesize factory = _factory;
hjonf396f602016-02-11 16:19:06 -0800304
305- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
306 configuration:(RTCConfiguration *)configuration
307 constraints:(RTCMediaConstraints *)constraints
308 delegate:(id<RTCPeerConnectionDelegate>)delegate {
309 NSParameterAssert(factory);
Jonas Oreland285f83d2020-02-07 10:30:08 +0100310 std::unique_ptr<webrtc::PeerConnectionDependencies> dependencies =
311 std::make_unique<webrtc::PeerConnectionDependencies>(nullptr);
312 return [self initWithDependencies:factory
313 configuration:configuration
314 constraints:constraints
315 dependencies:std::move(dependencies)
316 delegate:delegate];
317}
318
319- (instancetype)initWithDependencies:(RTCPeerConnectionFactory *)factory
320 configuration:(RTCConfiguration *)configuration
321 constraints:(RTCMediaConstraints *)constraints
322 dependencies:
323 (std::unique_ptr<webrtc::PeerConnectionDependencies>)dependencies
324 delegate:(id<RTCPeerConnectionDelegate>)delegate {
325 NSParameterAssert(factory);
326 NSParameterAssert(dependencies.get());
Henrik Boströme06c2dd2016-05-13 13:50:38 +0200327 std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
hbosa73ca562016-05-17 03:28:58 -0700328 [configuration createNativeConfiguration]);
329 if (!config) {
330 return nil;
331 }
hjonf396f602016-02-11 16:19:06 -0800332 if (self = [super init]) {
333 _observer.reset(new webrtc::PeerConnectionDelegateAdapter(self));
deadbeef5d0b6d82017-01-09 16:05:28 -0800334 _nativeConstraints = constraints.nativeConstraints;
Jonas Oreland285f83d2020-02-07 10:30:08 +0100335 CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(), config.get());
336
337 webrtc::PeerConnectionDependencies deps = std::move(*dependencies.release());
338 deps.observer = _observer.get();
339 _peerConnection = factory.nativeFactory->CreatePeerConnection(*config, std::move(deps));
340
skvlad588783a2016-08-11 14:29:25 -0700341 if (!_peerConnection) {
342 return nil;
343 }
Yura Yaroshevich5297bd22018-06-19 12:51:51 +0300344 _factory = factory;
hjonf396f602016-02-11 16:19:06 -0800345 _localStreams = [[NSMutableArray alloc] init];
346 _delegate = delegate;
347 }
348 return self;
349}
350
vopatop.skam96b6b832016-08-18 14:21:20 -0700351- (NSArray<RTCMediaStream *> *)localStreams {
hjonf396f602016-02-11 16:19:06 -0800352 return [_localStreams copy];
353}
354
355- (RTCSessionDescription *)localDescription {
356 const webrtc::SessionDescriptionInterface *description =
357 _peerConnection->local_description();
358 return description ?
359 [[RTCSessionDescription alloc] initWithNativeDescription:description]
360 : nil;
361}
362
363- (RTCSessionDescription *)remoteDescription {
364 const webrtc::SessionDescriptionInterface *description =
365 _peerConnection->remote_description();
366 return description ?
367 [[RTCSessionDescription alloc] initWithNativeDescription:description]
368 : nil;
369}
370
371- (RTCSignalingState)signalingState {
372 return [[self class]
373 signalingStateForNativeState:_peerConnection->signaling_state()];
374}
375
376- (RTCIceConnectionState)iceConnectionState {
377 return [[self class] iceConnectionStateForNativeState:
378 _peerConnection->ice_connection_state()];
379}
380
Jonas Olssoncfddbb72018-11-15 16:52:45 +0100381- (RTCPeerConnectionState)connectionState {
382 return [[self class] connectionStateForNativeState:_peerConnection->peer_connection_state()];
383}
384
hjonf396f602016-02-11 16:19:06 -0800385- (RTCIceGatheringState)iceGatheringState {
386 return [[self class] iceGatheringStateForNativeState:
387 _peerConnection->ice_gathering_state()];
388}
389
tkchinaac3eb22016-03-09 21:49:40 -0800390- (BOOL)setConfiguration:(RTCConfiguration *)configuration {
Henrik Boströme06c2dd2016-05-13 13:50:38 +0200391 std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
hbosa73ca562016-05-17 03:28:58 -0700392 [configuration createNativeConfiguration]);
393 if (!config) {
394 return NO;
395 }
deadbeef5d0b6d82017-01-09 16:05:28 -0800396 CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(),
397 config.get());
Niels Möller2579f0c2019-08-19 09:58:17 +0200398 return _peerConnection->SetConfiguration(*config).ok();
tkchinaac3eb22016-03-09 21:49:40 -0800399}
400
jtteh4eeb5372017-04-03 15:06:37 -0700401- (RTCConfiguration *)configuration {
402 webrtc::PeerConnectionInterface::RTCConfiguration config =
403 _peerConnection->GetConfiguration();
jtteh465faf02017-04-04 14:00:16 -0700404 return [[RTCConfiguration alloc] initWithNativeConfiguration:config];
jtteh4eeb5372017-04-03 15:06:37 -0700405}
406
hjonf396f602016-02-11 16:19:06 -0800407- (void)close {
408 _peerConnection->Close();
409}
410
411- (void)addIceCandidate:(RTCIceCandidate *)candidate {
kwibergbfefb032016-05-01 14:53:46 -0700412 std::unique_ptr<const webrtc::IceCandidateInterface> iceCandidate(
hjonf396f602016-02-11 16:19:06 -0800413 candidate.nativeCandidate);
414 _peerConnection->AddIceCandidate(iceCandidate.get());
415}
416
Honghai Zhangda2ba4d2016-05-23 11:53:14 -0700417- (void)removeIceCandidates:(NSArray<RTCIceCandidate *> *)iceCandidates {
418 std::vector<cricket::Candidate> candidates;
419 for (RTCIceCandidate *iceCandidate in iceCandidates) {
420 std::unique_ptr<const webrtc::IceCandidateInterface> candidate(
421 iceCandidate.nativeCandidate);
422 if (candidate) {
423 candidates.push_back(candidate->candidate());
424 // Need to fill the transport name from the sdp_mid.
425 candidates.back().set_transport_name(candidate->sdp_mid());
426 }
427 }
428 if (!candidates.empty()) {
429 _peerConnection->RemoveIceCandidates(candidates);
430 }
431}
432
hjonf396f602016-02-11 16:19:06 -0800433- (void)addStream:(RTCMediaStream *)stream {
hjona2f77982016-03-04 07:09:09 -0800434 if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
hjonf396f602016-02-11 16:19:06 -0800435 RTCLogError(@"Failed to add stream: %@", stream);
436 return;
437 }
438 [_localStreams addObject:stream];
439}
440
441- (void)removeStream:(RTCMediaStream *)stream {
442 _peerConnection->RemoveStream(stream.nativeMediaStream);
443 [_localStreams removeObject:stream];
444}
445
Seth Hampson513449e2018-03-06 09:35:56 -0800446- (RTCRtpSender *)addTrack:(RTCMediaStreamTrack *)track streamIds:(NSArray<NSString *> *)streamIds {
447 std::vector<std::string> nativeStreamIds;
448 for (NSString *streamId in streamIds) {
449 nativeStreamIds.push_back([streamId UTF8String]);
Steve Anton8cb344a2018-02-27 15:34:53 -0800450 }
451 webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenderOrError =
Seth Hampson513449e2018-03-06 09:35:56 -0800452 _peerConnection->AddTrack(track.nativeTrack, nativeStreamIds);
Steve Anton8cb344a2018-02-27 15:34:53 -0800453 if (!nativeSenderOrError.ok()) {
454 RTCLogError(@"Failed to add track %@: %s", track, nativeSenderOrError.error().message());
455 return nil;
456 }
Yura Yaroshevichef43aaf2018-07-09 19:16:32 +0300457 return [[RTCRtpSender alloc] initWithFactory:self.factory
458 nativeRtpSender:nativeSenderOrError.MoveValue()];
Steve Anton8cb344a2018-02-27 15:34:53 -0800459}
460
461- (BOOL)removeTrack:(RTCRtpSender *)sender {
462 bool result = _peerConnection->RemoveTrack(sender.nativeRtpSender);
463 if (!result) {
464 RTCLogError(@"Failed to remote track %@", sender);
465 }
466 return result;
467}
468
469- (RTCRtpTransceiver *)addTransceiverWithTrack:(RTCMediaStreamTrack *)track {
470 return [self addTransceiverWithTrack:track init:[[RTCRtpTransceiverInit alloc] init]];
471}
472
473- (RTCRtpTransceiver *)addTransceiverWithTrack:(RTCMediaStreamTrack *)track
474 init:(RTCRtpTransceiverInit *)init {
475 webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
476 _peerConnection->AddTransceiver(track.nativeTrack, init.nativeInit);
477 if (!nativeTransceiverOrError.ok()) {
478 RTCLogError(
479 @"Failed to add transceiver %@: %s", track, nativeTransceiverOrError.error().message());
480 return nil;
481 }
Yura Yaroshevich08f14dd2018-07-09 11:56:06 +0300482 return [[RTCRtpTransceiver alloc] initWithFactory:self.factory
483 nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
Steve Anton8cb344a2018-02-27 15:34:53 -0800484}
485
486- (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType {
487 return [self addTransceiverOfType:mediaType init:[[RTCRtpTransceiverInit alloc] init]];
488}
489
490- (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType
491 init:(RTCRtpTransceiverInit *)init {
492 webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
493 _peerConnection->AddTransceiver([RTCRtpReceiver nativeMediaTypeForMediaType:mediaType],
494 init.nativeInit);
495 if (!nativeTransceiverOrError.ok()) {
496 RTCLogError(@"Failed to add transceiver %@: %s",
497 [RTCRtpReceiver stringForMediaType:mediaType],
498 nativeTransceiverOrError.error().message());
499 return nil;
500 }
Yura Yaroshevich08f14dd2018-07-09 11:56:06 +0300501 return [[RTCRtpTransceiver alloc] initWithFactory:self.factory
502 nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
Steve Anton8cb344a2018-02-27 15:34:53 -0800503}
504
hjonf396f602016-02-11 16:19:06 -0800505- (void)offerForConstraints:(RTCMediaConstraints *)constraints
506 completionHandler:
507 (void (^)(RTCSessionDescription *sessionDescription,
508 NSError *error))completionHandler {
509 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
510 observer(new rtc::RefCountedObject
511 <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
Niels Möllerf06f9232018-08-07 12:32:18 +0200512 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
513 CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
514
515 _peerConnection->CreateOffer(observer, options);
hjonf396f602016-02-11 16:19:06 -0800516}
517
518- (void)answerForConstraints:(RTCMediaConstraints *)constraints
519 completionHandler:
520 (void (^)(RTCSessionDescription *sessionDescription,
521 NSError *error))completionHandler {
522 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
523 observer(new rtc::RefCountedObject
524 <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
Niels Möllerf06f9232018-08-07 12:32:18 +0200525 webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
526 CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
527
528 _peerConnection->CreateAnswer(observer, options);
hjonf396f602016-02-11 16:19:06 -0800529}
530
531- (void)setLocalDescription:(RTCSessionDescription *)sdp
532 completionHandler:(void (^)(NSError *error))completionHandler {
533 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
534 new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
535 completionHandler));
536 _peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
537}
538
539- (void)setRemoteDescription:(RTCSessionDescription *)sdp
540 completionHandler:(void (^)(NSError *error))completionHandler {
541 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
542 new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
543 completionHandler));
544 _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription);
545}
546
zstein8b476172017-09-05 14:43:03 -0700547- (BOOL)setBweMinBitrateBps:(nullable NSNumber *)minBitrateBps
548 currentBitrateBps:(nullable NSNumber *)currentBitrateBps
549 maxBitrateBps:(nullable NSNumber *)maxBitrateBps {
zstein03adb7c2017-08-09 14:29:42 -0700550 webrtc::PeerConnectionInterface::BitrateParameters params;
551 if (minBitrateBps != nil) {
Danil Chapovalov196100e2018-06-21 10:17:24 +0200552 params.min_bitrate_bps = absl::optional<int>(minBitrateBps.intValue);
zstein03adb7c2017-08-09 14:29:42 -0700553 }
554 if (currentBitrateBps != nil) {
Danil Chapovalov196100e2018-06-21 10:17:24 +0200555 params.current_bitrate_bps = absl::optional<int>(currentBitrateBps.intValue);
zstein03adb7c2017-08-09 14:29:42 -0700556 }
557 if (maxBitrateBps != nil) {
Danil Chapovalov196100e2018-06-21 10:17:24 +0200558 params.max_bitrate_bps = absl::optional<int>(maxBitrateBps.intValue);
zstein03adb7c2017-08-09 14:29:42 -0700559 }
560 return _peerConnection->SetBitrate(params).ok();
561}
562
ivoc14d5dbe2016-07-04 07:06:55 -0700563- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
564 maxSizeInBytes:(int64_t)maxSizeInBytes {
565 RTC_DCHECK(filePath.length);
566 RTC_DCHECK_GT(maxSizeInBytes, 0);
567 RTC_DCHECK(!_hasStartedRtcEventLog);
568 if (_hasStartedRtcEventLog) {
569 RTCLogError(@"Event logging already started.");
570 return NO;
571 }
Niels Möllerdec9f742019-06-03 15:25:20 +0200572 FILE *f = fopen(filePath.UTF8String, "wb");
573 if (!f) {
ivoc14d5dbe2016-07-04 07:06:55 -0700574 RTCLogError(@"Error opening file: %@. Error: %d", filePath, errno);
575 return NO;
576 }
Niels Möller695cf6a2019-05-13 12:27:23 +0200577 // TODO(eladalon): It would be better to not allow negative values into PC.
578 const size_t max_size = (maxSizeInBytes < 0) ? webrtc::RtcEventLog::kUnlimitedOutput :
579 rtc::saturated_cast<size_t>(maxSizeInBytes);
580
581 _hasStartedRtcEventLog = _peerConnection->StartRtcEventLog(
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200582 std::make_unique<webrtc::RtcEventLogOutputFile>(f, max_size));
ivoc14d5dbe2016-07-04 07:06:55 -0700583 return _hasStartedRtcEventLog;
584}
585
586- (void)stopRtcEventLog {
587 _peerConnection->StopRtcEventLog();
588 _hasStartedRtcEventLog = NO;
589}
590
skvladf3569c82016-04-29 15:30:16 -0700591- (RTCRtpSender *)senderWithKind:(NSString *)kind
592 streamId:(NSString *)streamId {
593 std::string nativeKind = [NSString stdStringForString:kind];
594 std::string nativeStreamId = [NSString stdStringForString:streamId];
595 rtc::scoped_refptr<webrtc::RtpSenderInterface> nativeSender(
596 _peerConnection->CreateSender(nativeKind, nativeStreamId));
597 return nativeSender ?
Yura Yaroshevichef43aaf2018-07-09 19:16:32 +0300598 [[RTCRtpSender alloc] initWithFactory:self.factory nativeRtpSender:nativeSender] :
599 nil;
skvladf3569c82016-04-29 15:30:16 -0700600}
601
skvlad79b4b872016-04-08 17:28:55 -0700602- (NSArray<RTCRtpSender *> *)senders {
603 std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenders(
604 _peerConnection->GetSenders());
605 NSMutableArray *senders = [[NSMutableArray alloc] init];
606 for (const auto &nativeSender : nativeSenders) {
607 RTCRtpSender *sender =
Yura Yaroshevichef43aaf2018-07-09 19:16:32 +0300608 [[RTCRtpSender alloc] initWithFactory:self.factory nativeRtpSender:nativeSender];
skvlad79b4b872016-04-08 17:28:55 -0700609 [senders addObject:sender];
610 }
611 return senders;
612}
613
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -0700614- (NSArray<RTCRtpReceiver *> *)receivers {
615 std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> nativeReceivers(
616 _peerConnection->GetReceivers());
617 NSMutableArray *receivers = [[NSMutableArray alloc] init];
618 for (const auto &nativeReceiver : nativeReceivers) {
619 RTCRtpReceiver *receiver =
Yura Yaroshevich7a16c542018-07-11 12:55:04 +0300620 [[RTCRtpReceiver alloc] initWithFactory:self.factory nativeRtpReceiver:nativeReceiver];
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -0700621 [receivers addObject:receiver];
622 }
623 return receivers;
624}
625
Steve Anton8cb344a2018-02-27 15:34:53 -0800626- (NSArray<RTCRtpTransceiver *> *)transceivers {
627 std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceivers(
628 _peerConnection->GetTransceivers());
629 NSMutableArray *transceivers = [[NSMutableArray alloc] init];
Mirko Bonadei739baf02019-01-27 17:29:42 +0100630 for (const auto &nativeTransceiver : nativeTransceivers) {
Yura Yaroshevich08f14dd2018-07-09 11:56:06 +0300631 RTCRtpTransceiver *transceiver = [[RTCRtpTransceiver alloc] initWithFactory:self.factory
632 nativeRtpTransceiver:nativeTransceiver];
Steve Anton8cb344a2018-02-27 15:34:53 -0800633 [transceivers addObject:transceiver];
634 }
635 return transceivers;
636}
637
hjonf396f602016-02-11 16:19:06 -0800638#pragma mark - Private
639
640+ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState:
641 (RTCSignalingState)state {
642 switch (state) {
643 case RTCSignalingStateStable:
644 return webrtc::PeerConnectionInterface::kStable;
645 case RTCSignalingStateHaveLocalOffer:
646 return webrtc::PeerConnectionInterface::kHaveLocalOffer;
647 case RTCSignalingStateHaveLocalPrAnswer:
648 return webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
649 case RTCSignalingStateHaveRemoteOffer:
650 return webrtc::PeerConnectionInterface::kHaveRemoteOffer;
651 case RTCSignalingStateHaveRemotePrAnswer:
652 return webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
653 case RTCSignalingStateClosed:
654 return webrtc::PeerConnectionInterface::kClosed;
655 }
656}
657
658+ (RTCSignalingState)signalingStateForNativeState:
659 (webrtc::PeerConnectionInterface::SignalingState)nativeState {
660 switch (nativeState) {
661 case webrtc::PeerConnectionInterface::kStable:
662 return RTCSignalingStateStable;
663 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
664 return RTCSignalingStateHaveLocalOffer;
665 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
666 return RTCSignalingStateHaveLocalPrAnswer;
667 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
668 return RTCSignalingStateHaveRemoteOffer;
669 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
670 return RTCSignalingStateHaveRemotePrAnswer;
671 case webrtc::PeerConnectionInterface::kClosed:
672 return RTCSignalingStateClosed;
673 }
674}
675
676+ (NSString *)stringForSignalingState:(RTCSignalingState)state {
677 switch (state) {
678 case RTCSignalingStateStable:
679 return @"STABLE";
680 case RTCSignalingStateHaveLocalOffer:
681 return @"HAVE_LOCAL_OFFER";
682 case RTCSignalingStateHaveLocalPrAnswer:
683 return @"HAVE_LOCAL_PRANSWER";
684 case RTCSignalingStateHaveRemoteOffer:
685 return @"HAVE_REMOTE_OFFER";
686 case RTCSignalingStateHaveRemotePrAnswer:
687 return @"HAVE_REMOTE_PRANSWER";
688 case RTCSignalingStateClosed:
689 return @"CLOSED";
690 }
691}
692
Jonas Olssoncfddbb72018-11-15 16:52:45 +0100693+ (webrtc::PeerConnectionInterface::PeerConnectionState)nativeConnectionStateForState:
694 (RTCPeerConnectionState)state {
695 switch (state) {
696 case RTCPeerConnectionStateNew:
697 return webrtc::PeerConnectionInterface::PeerConnectionState::kNew;
698 case RTCPeerConnectionStateConnecting:
699 return webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting;
700 case RTCPeerConnectionStateConnected:
701 return webrtc::PeerConnectionInterface::PeerConnectionState::kConnected;
702 case RTCPeerConnectionStateFailed:
703 return webrtc::PeerConnectionInterface::PeerConnectionState::kFailed;
704 case RTCPeerConnectionStateDisconnected:
705 return webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected;
706 case RTCPeerConnectionStateClosed:
707 return webrtc::PeerConnectionInterface::PeerConnectionState::kClosed;
708 }
709}
710
711+ (RTCPeerConnectionState)connectionStateForNativeState:
712 (webrtc::PeerConnectionInterface::PeerConnectionState)nativeState {
713 switch (nativeState) {
714 case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
715 return RTCPeerConnectionStateNew;
716 case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
717 return RTCPeerConnectionStateConnecting;
718 case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
719 return RTCPeerConnectionStateConnected;
720 case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
721 return RTCPeerConnectionStateFailed;
722 case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
723 return RTCPeerConnectionStateDisconnected;
724 case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
725 return RTCPeerConnectionStateClosed;
726 }
727}
728
729+ (NSString *)stringForConnectionState:(RTCPeerConnectionState)state {
730 switch (state) {
731 case RTCPeerConnectionStateNew:
732 return @"NEW";
733 case RTCPeerConnectionStateConnecting:
734 return @"CONNECTING";
735 case RTCPeerConnectionStateConnected:
736 return @"CONNECTED";
737 case RTCPeerConnectionStateFailed:
738 return @"FAILED";
739 case RTCPeerConnectionStateDisconnected:
740 return @"DISCONNECTED";
741 case RTCPeerConnectionStateClosed:
742 return @"CLOSED";
743 }
744}
745
hjonf396f602016-02-11 16:19:06 -0800746+ (webrtc::PeerConnectionInterface::IceConnectionState)
747 nativeIceConnectionStateForState:(RTCIceConnectionState)state {
748 switch (state) {
749 case RTCIceConnectionStateNew:
750 return webrtc::PeerConnectionInterface::kIceConnectionNew;
751 case RTCIceConnectionStateChecking:
752 return webrtc::PeerConnectionInterface::kIceConnectionChecking;
753 case RTCIceConnectionStateConnected:
754 return webrtc::PeerConnectionInterface::kIceConnectionConnected;
755 case RTCIceConnectionStateCompleted:
756 return webrtc::PeerConnectionInterface::kIceConnectionCompleted;
757 case RTCIceConnectionStateFailed:
758 return webrtc::PeerConnectionInterface::kIceConnectionFailed;
759 case RTCIceConnectionStateDisconnected:
760 return webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
761 case RTCIceConnectionStateClosed:
762 return webrtc::PeerConnectionInterface::kIceConnectionClosed;
hjon8bbbf2c2016-03-14 13:15:44 -0700763 case RTCIceConnectionStateCount:
hjonf396f602016-02-11 16:19:06 -0800764 return webrtc::PeerConnectionInterface::kIceConnectionMax;
765 }
766}
767
768+ (RTCIceConnectionState)iceConnectionStateForNativeState:
769 (webrtc::PeerConnectionInterface::IceConnectionState)nativeState {
770 switch (nativeState) {
771 case webrtc::PeerConnectionInterface::kIceConnectionNew:
772 return RTCIceConnectionStateNew;
773 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
774 return RTCIceConnectionStateChecking;
775 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
776 return RTCIceConnectionStateConnected;
777 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
778 return RTCIceConnectionStateCompleted;
779 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
780 return RTCIceConnectionStateFailed;
781 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
782 return RTCIceConnectionStateDisconnected;
783 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
784 return RTCIceConnectionStateClosed;
785 case webrtc::PeerConnectionInterface::kIceConnectionMax:
hjon8bbbf2c2016-03-14 13:15:44 -0700786 return RTCIceConnectionStateCount;
hjonf396f602016-02-11 16:19:06 -0800787 }
788}
789
790+ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state {
791 switch (state) {
792 case RTCIceConnectionStateNew:
793 return @"NEW";
794 case RTCIceConnectionStateChecking:
795 return @"CHECKING";
796 case RTCIceConnectionStateConnected:
797 return @"CONNECTED";
798 case RTCIceConnectionStateCompleted:
799 return @"COMPLETED";
800 case RTCIceConnectionStateFailed:
801 return @"FAILED";
802 case RTCIceConnectionStateDisconnected:
803 return @"DISCONNECTED";
804 case RTCIceConnectionStateClosed:
805 return @"CLOSED";
hjon8bbbf2c2016-03-14 13:15:44 -0700806 case RTCIceConnectionStateCount:
807 return @"COUNT";
hjonf396f602016-02-11 16:19:06 -0800808 }
809}
810
811+ (webrtc::PeerConnectionInterface::IceGatheringState)
812 nativeIceGatheringStateForState:(RTCIceGatheringState)state {
813 switch (state) {
814 case RTCIceGatheringStateNew:
815 return webrtc::PeerConnectionInterface::kIceGatheringNew;
816 case RTCIceGatheringStateGathering:
817 return webrtc::PeerConnectionInterface::kIceGatheringGathering;
818 case RTCIceGatheringStateComplete:
819 return webrtc::PeerConnectionInterface::kIceGatheringComplete;
820 }
821}
822
823+ (RTCIceGatheringState)iceGatheringStateForNativeState:
824 (webrtc::PeerConnectionInterface::IceGatheringState)nativeState {
825 switch (nativeState) {
826 case webrtc::PeerConnectionInterface::kIceGatheringNew:
827 return RTCIceGatheringStateNew;
828 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
829 return RTCIceGatheringStateGathering;
830 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
831 return RTCIceGatheringStateComplete;
832 }
833}
834
835+ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state {
836 switch (state) {
837 case RTCIceGatheringStateNew:
838 return @"NEW";
839 case RTCIceGatheringStateGathering:
840 return @"GATHERING";
841 case RTCIceGatheringStateComplete:
842 return @"COMPLETE";
843 }
844}
845
846+ (webrtc::PeerConnectionInterface::StatsOutputLevel)
847 nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level {
848 switch (level) {
849 case RTCStatsOutputLevelStandard:
850 return webrtc::PeerConnectionInterface::kStatsOutputLevelStandard;
851 case RTCStatsOutputLevelDebug:
852 return webrtc::PeerConnectionInterface::kStatsOutputLevelDebug;
853 }
854}
855
hjonf396f602016-02-11 16:19:06 -0800856- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)nativePeerConnection {
857 return _peerConnection;
858}
859
860@end