1/*
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
11#import "RTCPeerConnection+Private.h"
12
13#import "RTCConfiguration+Private.h"
14#import "RTCDataChannel+Private.h"
15#import "RTCIceCandidate+Private.h"
16#import "RTCLegacyStatsReport+Private.h"
17#import "RTCMediaConstraints+Private.h"
18#import "RTCMediaStream+Private.h"
19#import "RTCMediaStreamTrack+Private.h"
20#import "RTCPeerConnectionFactory+Private.h"
21#import "RTCRtpReceiver+Private.h"
22#import "RTCRtpSender+Private.h"
23#import "RTCRtpTransceiver+Private.h"
24#import "RTCSessionDescription+Private.h"
25#import "base/RTCLogging.h"
26#import "helpers/NSString+StdString.h"
27
28#include <memory>
29
30#include "api/jsep_ice_candidate.h"
31#include "api/rtc_event_log_output_file.h"
32#include "rtc_base/checks.h"
33#include "rtc_base/numerics/safe_conversions.h"
34
35NSString *const kRTCPeerConnectionErrorDomain = @"org.webrtc.RTC_OBJC_TYPE(RTCPeerConnection)";
36int const kRTCPeerConnnectionSessionDescriptionError = -1;
37
38namespace webrtc {
39
40class CreateSessionDescriptionObserverAdapter
41    : public CreateSessionDescriptionObserver {
42 public:
43  CreateSessionDescriptionObserverAdapter(void (^completionHandler)(
44      RTC_OBJC_TYPE(RTCSessionDescription) * sessionDescription, NSError *error)) {
45    completion_handler_ = completionHandler;
46  }
47
48  ~CreateSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
49
50  void OnSuccess(SessionDescriptionInterface *desc) override {
51    RTC_DCHECK(completion_handler_);
52    std::unique_ptr<webrtc::SessionDescriptionInterface> description =
53        std::unique_ptr<webrtc::SessionDescriptionInterface>(desc);
54    RTC_OBJC_TYPE(RTCSessionDescription) *session =
55        [[RTC_OBJC_TYPE(RTCSessionDescription) alloc] initWithNativeDescription:description.get()];
56    completion_handler_(session, nil);
57    completion_handler_ = nil;
58  }
59
60  void OnFailure(RTCError error) override {
61    RTC_DCHECK(completion_handler_);
62    // TODO(hta): Add handling of error.type()
63    NSString *str = [NSString stringForStdString:error.message()];
64    NSError* err =
65        [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
66                            code:kRTCPeerConnnectionSessionDescriptionError
67                        userInfo:@{ NSLocalizedDescriptionKey : str }];
68    completion_handler_(nil, err);
69    completion_handler_ = nil;
70  }
71
72 private:
73  void (^completion_handler_)(RTC_OBJC_TYPE(RTCSessionDescription) * sessionDescription,
74                              NSError *error);
75};
76
77class SetSessionDescriptionObserverAdapter :
78    public SetSessionDescriptionObserver {
79 public:
80  SetSessionDescriptionObserverAdapter(void (^completionHandler)
81      (NSError *error)) {
82    completion_handler_ = completionHandler;
83  }
84
85  ~SetSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
86
87  void OnSuccess() override {
88    RTC_DCHECK(completion_handler_);
89    completion_handler_(nil);
90    completion_handler_ = nil;
91  }
92
93  void OnFailure(RTCError error) override {
94    RTC_DCHECK(completion_handler_);
95    // TODO(hta): Add handling of error.type()
96    NSString *str = [NSString stringForStdString:error.message()];
97    NSError* err =
98        [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
99                            code:kRTCPeerConnnectionSessionDescriptionError
100                        userInfo:@{ NSLocalizedDescriptionKey : str }];
101    completion_handler_(err);
102    completion_handler_ = nil;
103  }
104
105 private:
106  void (^completion_handler_)(NSError *error);
107};
108
109PeerConnectionDelegateAdapter::PeerConnectionDelegateAdapter(RTC_OBJC_TYPE(RTCPeerConnection) *
110                                                             peerConnection) {
111  peer_connection_ = peerConnection;
112}
113
114PeerConnectionDelegateAdapter::~PeerConnectionDelegateAdapter() {
115  peer_connection_ = nil;
116}
117
118void PeerConnectionDelegateAdapter::OnSignalingChange(
119    PeerConnectionInterface::SignalingState new_state) {
120  RTCSignalingState state =
121      [[RTC_OBJC_TYPE(RTCPeerConnection) class] signalingStateForNativeState:new_state];
122  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
123  [peer_connection.delegate peerConnection:peer_connection
124                   didChangeSignalingState:state];
125}
126
127void PeerConnectionDelegateAdapter::OnAddStream(
128    rtc::scoped_refptr<MediaStreamInterface> stream) {
129  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
130  RTC_OBJC_TYPE(RTCMediaStream) *mediaStream =
131      [[RTC_OBJC_TYPE(RTCMediaStream) alloc] initWithFactory:peer_connection.factory
132                                           nativeMediaStream:stream];
133  [peer_connection.delegate peerConnection:peer_connection
134                              didAddStream:mediaStream];
135}
136
137void PeerConnectionDelegateAdapter::OnRemoveStream(
138    rtc::scoped_refptr<MediaStreamInterface> stream) {
139  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
140  RTC_OBJC_TYPE(RTCMediaStream) *mediaStream =
141      [[RTC_OBJC_TYPE(RTCMediaStream) alloc] initWithFactory:peer_connection.factory
142                                           nativeMediaStream:stream];
143
144  [peer_connection.delegate peerConnection:peer_connection
145                           didRemoveStream:mediaStream];
146}
147
148void PeerConnectionDelegateAdapter::OnTrack(
149    rtc::scoped_refptr<RtpTransceiverInterface> nativeTransceiver) {
150  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
151  RTC_OBJC_TYPE(RTCRtpTransceiver) *transceiver =
152      [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc] initWithFactory:peer_connection.factory
153                                           nativeRtpTransceiver:nativeTransceiver];
154  if ([peer_connection.delegate
155          respondsToSelector:@selector(peerConnection:didStartReceivingOnTransceiver:)]) {
156    [peer_connection.delegate peerConnection:peer_connection
157              didStartReceivingOnTransceiver:transceiver];
158  }
159}
160
161void PeerConnectionDelegateAdapter::OnDataChannel(
162    rtc::scoped_refptr<DataChannelInterface> data_channel) {
163  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
164  RTC_OBJC_TYPE(RTCDataChannel) *dataChannel =
165      [[RTC_OBJC_TYPE(RTCDataChannel) alloc] initWithFactory:peer_connection.factory
166                                           nativeDataChannel:data_channel];
167  [peer_connection.delegate peerConnection:peer_connection
168                        didOpenDataChannel:dataChannel];
169}
170
171void PeerConnectionDelegateAdapter::OnRenegotiationNeeded() {
172  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
173  [peer_connection.delegate peerConnectionShouldNegotiate:peer_connection];
174}
175
176void PeerConnectionDelegateAdapter::OnIceConnectionChange(
177    PeerConnectionInterface::IceConnectionState new_state) {
178  RTCIceConnectionState state =
179      [RTC_OBJC_TYPE(RTCPeerConnection) iceConnectionStateForNativeState:new_state];
180  [peer_connection_.delegate peerConnection:peer_connection_ didChangeIceConnectionState:state];
181}
182
183void PeerConnectionDelegateAdapter::OnStandardizedIceConnectionChange(
184    PeerConnectionInterface::IceConnectionState new_state) {
185  if ([peer_connection_.delegate
186          respondsToSelector:@selector(peerConnection:didChangeStandardizedIceConnectionState:)]) {
187    RTCIceConnectionState state =
188        [RTC_OBJC_TYPE(RTCPeerConnection) iceConnectionStateForNativeState:new_state];
189    [peer_connection_.delegate peerConnection:peer_connection_
190        didChangeStandardizedIceConnectionState:state];
191  }
192}
193
194void PeerConnectionDelegateAdapter::OnConnectionChange(
195    PeerConnectionInterface::PeerConnectionState new_state) {
196  if ([peer_connection_.delegate
197          respondsToSelector:@selector(peerConnection:didChangeConnectionState:)]) {
198    RTCPeerConnectionState state =
199        [RTC_OBJC_TYPE(RTCPeerConnection) connectionStateForNativeState:new_state];
200    [peer_connection_.delegate peerConnection:peer_connection_ didChangeConnectionState:state];
201  }
202}
203
204void PeerConnectionDelegateAdapter::OnIceGatheringChange(
205    PeerConnectionInterface::IceGatheringState new_state) {
206  RTCIceGatheringState state =
207      [[RTC_OBJC_TYPE(RTCPeerConnection) class] iceGatheringStateForNativeState:new_state];
208  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
209  [peer_connection.delegate peerConnection:peer_connection
210                didChangeIceGatheringState:state];
211}
212
213void PeerConnectionDelegateAdapter::OnIceCandidate(
214    const IceCandidateInterface *candidate) {
215  RTC_OBJC_TYPE(RTCIceCandidate) *iceCandidate =
216      [[RTC_OBJC_TYPE(RTCIceCandidate) alloc] initWithNativeCandidate:candidate];
217  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
218  [peer_connection.delegate peerConnection:peer_connection
219                   didGenerateIceCandidate:iceCandidate];
220}
221
222void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
223    const std::vector<cricket::Candidate>& candidates) {
224  NSMutableArray* ice_candidates =
225      [NSMutableArray arrayWithCapacity:candidates.size()];
226  for (const auto& candidate : candidates) {
227    std::unique_ptr<JsepIceCandidate> candidate_wrapper(
228        new JsepIceCandidate(candidate.transport_name(), -1, candidate));
229    RTC_OBJC_TYPE(RTCIceCandidate) *ice_candidate =
230        [[RTC_OBJC_TYPE(RTCIceCandidate) alloc] initWithNativeCandidate:candidate_wrapper.get()];
231    [ice_candidates addObject:ice_candidate];
232  }
233  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
234  [peer_connection.delegate peerConnection:peer_connection
235                    didRemoveIceCandidates:ice_candidates];
236}
237
238void PeerConnectionDelegateAdapter::OnIceSelectedCandidatePairChanged(
239    const cricket::CandidatePairChangeEvent &event) {
240  const auto &selected_pair = event.selected_candidate_pair;
241  auto local_candidate_wrapper = std::make_unique<JsepIceCandidate>(
242      selected_pair.local_candidate().transport_name(), -1, selected_pair.local_candidate());
243  RTC_OBJC_TYPE(RTCIceCandidate) *local_candidate = [[RTC_OBJC_TYPE(RTCIceCandidate) alloc]
244      initWithNativeCandidate:local_candidate_wrapper.release()];
245  auto remote_candidate_wrapper = std::make_unique<JsepIceCandidate>(
246      selected_pair.remote_candidate().transport_name(), -1, selected_pair.remote_candidate());
247  RTC_OBJC_TYPE(RTCIceCandidate) *remote_candidate = [[RTC_OBJC_TYPE(RTCIceCandidate) alloc]
248      initWithNativeCandidate:remote_candidate_wrapper.release()];
249  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
250  NSString *nsstr_reason = [NSString stringForStdString:event.reason];
251  if ([peer_connection.delegate
252          respondsToSelector:@selector
253          (peerConnection:didChangeLocalCandidate:remoteCandidate:lastReceivedMs:changeReason:)]) {
254    [peer_connection.delegate peerConnection:peer_connection
255                     didChangeLocalCandidate:local_candidate
256                             remoteCandidate:remote_candidate
257                              lastReceivedMs:event.last_data_received_ms
258                                changeReason:nsstr_reason];
259  }
260}
261
262void PeerConnectionDelegateAdapter::OnAddTrack(
263    rtc::scoped_refptr<RtpReceiverInterface> receiver,
264    const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) {
265  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
266  if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:
267                                                             didAddReceiver:streams:)]) {
268    NSMutableArray *mediaStreams = [NSMutableArray arrayWithCapacity:streams.size()];
269    for (const auto &nativeStream : streams) {
270      RTC_OBJC_TYPE(RTCMediaStream) *mediaStream =
271          [[RTC_OBJC_TYPE(RTCMediaStream) alloc] initWithFactory:peer_connection.factory
272                                               nativeMediaStream:nativeStream];
273      [mediaStreams addObject:mediaStream];
274    }
275    RTC_OBJC_TYPE(RTCRtpReceiver) *rtpReceiver =
276        [[RTC_OBJC_TYPE(RTCRtpReceiver) alloc] initWithFactory:peer_connection.factory
277                                             nativeRtpReceiver:receiver];
278
279    [peer_connection.delegate peerConnection:peer_connection
280                              didAddReceiver:rtpReceiver
281                                     streams:mediaStreams];
282  }
283}
284
285void PeerConnectionDelegateAdapter::OnRemoveTrack(
286    rtc::scoped_refptr<RtpReceiverInterface> receiver) {
287  RTC_OBJC_TYPE(RTCPeerConnection) *peer_connection = peer_connection_;
288  if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:didRemoveReceiver:)]) {
289    RTC_OBJC_TYPE(RTCRtpReceiver) *rtpReceiver =
290        [[RTC_OBJC_TYPE(RTCRtpReceiver) alloc] initWithFactory:peer_connection.factory
291                                             nativeRtpReceiver:receiver];
292    [peer_connection.delegate peerConnection:peer_connection didRemoveReceiver:rtpReceiver];
293  }
294}
295
296}  // namespace webrtc
297
298@implementation RTC_OBJC_TYPE (RTCPeerConnection) {
299  RTC_OBJC_TYPE(RTCPeerConnectionFactory) * _factory;
300  NSMutableArray<RTC_OBJC_TYPE(RTCMediaStream) *> *_localStreams;
301  std::unique_ptr<webrtc::PeerConnectionDelegateAdapter> _observer;
302  rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
303  std::unique_ptr<webrtc::MediaConstraints> _nativeConstraints;
304  BOOL _hasStartedRtcEventLog;
305}
306
307@synthesize delegate = _delegate;
308@synthesize factory = _factory;
309
310- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
311                  configuration:(RTC_OBJC_TYPE(RTCConfiguration) *)configuration
312                    constraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints
313                       delegate:(id<RTC_OBJC_TYPE(RTCPeerConnectionDelegate)>)delegate {
314  NSParameterAssert(factory);
315  std::unique_ptr<webrtc::PeerConnectionDependencies> dependencies =
316      std::make_unique<webrtc::PeerConnectionDependencies>(nullptr);
317  return [self initWithDependencies:factory
318                      configuration:configuration
319                        constraints:constraints
320                       dependencies:std::move(dependencies)
321                           delegate:delegate];
322}
323
324- (instancetype)initWithDependencies:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
325                       configuration:(RTC_OBJC_TYPE(RTCConfiguration) *)configuration
326                         constraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints
327                        dependencies:
328                            (std::unique_ptr<webrtc::PeerConnectionDependencies>)dependencies
329                            delegate:(id<RTC_OBJC_TYPE(RTCPeerConnectionDelegate)>)delegate {
330  NSParameterAssert(factory);
331  NSParameterAssert(dependencies.get());
332  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
333      [configuration createNativeConfiguration]);
334  if (!config) {
335    return nil;
336  }
337  if (self = [super init]) {
338    _observer.reset(new webrtc::PeerConnectionDelegateAdapter(self));
339    _nativeConstraints = constraints.nativeConstraints;
340    CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(), config.get());
341
342    webrtc::PeerConnectionDependencies deps = std::move(*dependencies.release());
343    deps.observer = _observer.get();
344    _peerConnection = factory.nativeFactory->CreatePeerConnection(*config, std::move(deps));
345
346    if (!_peerConnection) {
347      return nil;
348    }
349    _factory = factory;
350    _localStreams = [[NSMutableArray alloc] init];
351    _delegate = delegate;
352  }
353  return self;
354}
355
356- (NSArray<RTC_OBJC_TYPE(RTCMediaStream) *> *)localStreams {
357  return [_localStreams copy];
358}
359
360- (RTC_OBJC_TYPE(RTCSessionDescription) *)localDescription {
361  // It's only safe to operate on SessionDescriptionInterface on the signaling thread.
362  return _peerConnection->signaling_thread()->Invoke<RTC_OBJC_TYPE(RTCSessionDescription) *>(
363      RTC_FROM_HERE, [self] {
364        const webrtc::SessionDescriptionInterface *description =
365            _peerConnection->local_description();
366        return description ?
367            [[RTC_OBJC_TYPE(RTCSessionDescription) alloc] initWithNativeDescription:description] :
368            nil;
369      });
370}
371
372- (RTC_OBJC_TYPE(RTCSessionDescription) *)remoteDescription {
373  // It's only safe to operate on SessionDescriptionInterface on the signaling thread.
374  return _peerConnection->signaling_thread()->Invoke<RTC_OBJC_TYPE(RTCSessionDescription) *>(
375      RTC_FROM_HERE, [self] {
376        const webrtc::SessionDescriptionInterface *description =
377            _peerConnection->remote_description();
378        return description ?
379            [[RTC_OBJC_TYPE(RTCSessionDescription) alloc] initWithNativeDescription:description] :
380            nil;
381      });
382}
383
384- (RTCSignalingState)signalingState {
385  return [[self class]
386      signalingStateForNativeState:_peerConnection->signaling_state()];
387}
388
389- (RTCIceConnectionState)iceConnectionState {
390  return [[self class] iceConnectionStateForNativeState:
391      _peerConnection->ice_connection_state()];
392}
393
394- (RTCPeerConnectionState)connectionState {
395  return [[self class] connectionStateForNativeState:_peerConnection->peer_connection_state()];
396}
397
398- (RTCIceGatheringState)iceGatheringState {
399  return [[self class] iceGatheringStateForNativeState:
400      _peerConnection->ice_gathering_state()];
401}
402
403- (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCConfiguration) *)configuration {
404  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
405      [configuration createNativeConfiguration]);
406  if (!config) {
407    return NO;
408  }
409  CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(),
410                                      config.get());
411  return _peerConnection->SetConfiguration(*config).ok();
412}
413
414- (RTC_OBJC_TYPE(RTCConfiguration) *)configuration {
415  webrtc::PeerConnectionInterface::RTCConfiguration config =
416    _peerConnection->GetConfiguration();
417  return [[RTC_OBJC_TYPE(RTCConfiguration) alloc] initWithNativeConfiguration:config];
418}
419
420- (void)close {
421  _peerConnection->Close();
422}
423
424- (void)addIceCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)candidate {
425  std::unique_ptr<const webrtc::IceCandidateInterface> iceCandidate(
426      candidate.nativeCandidate);
427  _peerConnection->AddIceCandidate(iceCandidate.get());
428}
429
430- (void)removeIceCandidates:(NSArray<RTC_OBJC_TYPE(RTCIceCandidate) *> *)iceCandidates {
431  std::vector<cricket::Candidate> candidates;
432  for (RTC_OBJC_TYPE(RTCIceCandidate) * iceCandidate in iceCandidates) {
433    std::unique_ptr<const webrtc::IceCandidateInterface> candidate(
434        iceCandidate.nativeCandidate);
435    if (candidate) {
436      candidates.push_back(candidate->candidate());
437      // Need to fill the transport name from the sdp_mid.
438      candidates.back().set_transport_name(candidate->sdp_mid());
439    }
440  }
441  if (!candidates.empty()) {
442    _peerConnection->RemoveIceCandidates(candidates);
443  }
444}
445
446- (void)addStream:(RTC_OBJC_TYPE(RTCMediaStream) *)stream {
447  if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
448    RTCLogError(@"Failed to add stream: %@", stream);
449    return;
450  }
451  [_localStreams addObject:stream];
452}
453
454- (void)removeStream:(RTC_OBJC_TYPE(RTCMediaStream) *)stream {
455  _peerConnection->RemoveStream(stream.nativeMediaStream);
456  [_localStreams removeObject:stream];
457}
458
459- (RTC_OBJC_TYPE(RTCRtpSender) *)addTrack:(RTC_OBJC_TYPE(RTCMediaStreamTrack) *)track
460                                streamIds:(NSArray<NSString *> *)streamIds {
461  std::vector<std::string> nativeStreamIds;
462  for (NSString *streamId in streamIds) {
463    nativeStreamIds.push_back([streamId UTF8String]);
464  }
465  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenderOrError =
466      _peerConnection->AddTrack(track.nativeTrack, nativeStreamIds);
467  if (!nativeSenderOrError.ok()) {
468    RTCLogError(@"Failed to add track %@: %s", track, nativeSenderOrError.error().message());
469    return nil;
470  }
471  return [[RTC_OBJC_TYPE(RTCRtpSender) alloc] initWithFactory:self.factory
472                                              nativeRtpSender:nativeSenderOrError.MoveValue()];
473}
474
475- (BOOL)removeTrack:(RTC_OBJC_TYPE(RTCRtpSender) *)sender {
476  bool result = _peerConnection->RemoveTrack(sender.nativeRtpSender);
477  if (!result) {
478    RTCLogError(@"Failed to remote track %@", sender);
479  }
480  return result;
481}
482
483- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)addTransceiverWithTrack:
484    (RTC_OBJC_TYPE(RTCMediaStreamTrack) *)track {
485  return [self addTransceiverWithTrack:track
486                                  init:[[RTC_OBJC_TYPE(RTCRtpTransceiverInit) alloc] init]];
487}
488
489- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)
490    addTransceiverWithTrack:(RTC_OBJC_TYPE(RTCMediaStreamTrack) *)track
491                       init:(RTC_OBJC_TYPE(RTCRtpTransceiverInit) *)init {
492  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
493      _peerConnection->AddTransceiver(track.nativeTrack, init.nativeInit);
494  if (!nativeTransceiverOrError.ok()) {
495    RTCLogError(
496        @"Failed to add transceiver %@: %s", track, nativeTransceiverOrError.error().message());
497    return nil;
498  }
499  return [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc]
500           initWithFactory:self.factory
501      nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
502}
503
504- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)addTransceiverOfType:(RTCRtpMediaType)mediaType {
505  return [self addTransceiverOfType:mediaType
506                               init:[[RTC_OBJC_TYPE(RTCRtpTransceiverInit) alloc] init]];
507}
508
509- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)addTransceiverOfType:(RTCRtpMediaType)mediaType
510                                                      init:(RTC_OBJC_TYPE(RTCRtpTransceiverInit) *)
511                                                               init {
512  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
513      _peerConnection->AddTransceiver(
514          [RTC_OBJC_TYPE(RTCRtpReceiver) nativeMediaTypeForMediaType:mediaType], init.nativeInit);
515  if (!nativeTransceiverOrError.ok()) {
516    RTCLogError(@"Failed to add transceiver %@: %s",
517                [RTC_OBJC_TYPE(RTCRtpReceiver) stringForMediaType:mediaType],
518                nativeTransceiverOrError.error().message());
519    return nil;
520  }
521  return [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc]
522           initWithFactory:self.factory
523      nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
524}
525
526- (void)offerForConstraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints
527          completionHandler:(void (^)(RTC_OBJC_TYPE(RTCSessionDescription) * sessionDescription,
528                                      NSError *error))completionHandler {
529  rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
530      observer(new rtc::RefCountedObject
531          <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
532  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
533  CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
534
535  _peerConnection->CreateOffer(observer, options);
536}
537
538- (void)answerForConstraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints
539           completionHandler:(void (^)(RTC_OBJC_TYPE(RTCSessionDescription) * sessionDescription,
540                                       NSError *error))completionHandler {
541  rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
542      observer(new rtc::RefCountedObject
543          <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
544  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
545  CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
546
547  _peerConnection->CreateAnswer(observer, options);
548}
549
550- (void)setLocalDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
551          completionHandler:(void (^)(NSError *error))completionHandler {
552  rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
553      new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
554          completionHandler));
555  _peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
556}
557
558- (void)setRemoteDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
559           completionHandler:(void (^)(NSError *error))completionHandler {
560  rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
561      new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
562          completionHandler));
563  _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription);
564}
565
566- (BOOL)setBweMinBitrateBps:(nullable NSNumber *)minBitrateBps
567          currentBitrateBps:(nullable NSNumber *)currentBitrateBps
568              maxBitrateBps:(nullable NSNumber *)maxBitrateBps {
569  webrtc::BitrateSettings params;
570  if (minBitrateBps != nil) {
571    params.min_bitrate_bps = absl::optional<int>(minBitrateBps.intValue);
572  }
573  if (currentBitrateBps != nil) {
574    params.start_bitrate_bps = absl::optional<int>(currentBitrateBps.intValue);
575  }
576  if (maxBitrateBps != nil) {
577    params.max_bitrate_bps = absl::optional<int>(maxBitrateBps.intValue);
578  }
579  return _peerConnection->SetBitrate(params).ok();
580}
581
582- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
583                      maxSizeInBytes:(int64_t)maxSizeInBytes {
584  RTC_DCHECK(filePath.length);
585  RTC_DCHECK_GT(maxSizeInBytes, 0);
586  RTC_DCHECK(!_hasStartedRtcEventLog);
587  if (_hasStartedRtcEventLog) {
588    RTCLogError(@"Event logging already started.");
589    return NO;
590  }
591  FILE *f = fopen(filePath.UTF8String, "wb");
592  if (!f) {
593    RTCLogError(@"Error opening file: %@. Error: %d", filePath, errno);
594    return NO;
595  }
596  // TODO(eladalon): It would be better to not allow negative values into PC.
597  const size_t max_size = (maxSizeInBytes < 0) ? webrtc::RtcEventLog::kUnlimitedOutput :
598                                                 rtc::saturated_cast<size_t>(maxSizeInBytes);
599
600  _hasStartedRtcEventLog = _peerConnection->StartRtcEventLog(
601      std::make_unique<webrtc::RtcEventLogOutputFile>(f, max_size));
602  return _hasStartedRtcEventLog;
603}
604
605- (void)stopRtcEventLog {
606  _peerConnection->StopRtcEventLog();
607  _hasStartedRtcEventLog = NO;
608}
609
610- (RTC_OBJC_TYPE(RTCRtpSender) *)senderWithKind:(NSString *)kind streamId:(NSString *)streamId {
611  std::string nativeKind = [NSString stdStringForString:kind];
612  std::string nativeStreamId = [NSString stdStringForString:streamId];
613  rtc::scoped_refptr<webrtc::RtpSenderInterface> nativeSender(
614      _peerConnection->CreateSender(nativeKind, nativeStreamId));
615  return nativeSender ? [[RTC_OBJC_TYPE(RTCRtpSender) alloc] initWithFactory:self.factory
616                                                             nativeRtpSender:nativeSender] :
617                        nil;
618}
619
620- (NSArray<RTC_OBJC_TYPE(RTCRtpSender) *> *)senders {
621  std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenders(
622      _peerConnection->GetSenders());
623  NSMutableArray *senders = [[NSMutableArray alloc] init];
624  for (const auto &nativeSender : nativeSenders) {
625    RTC_OBJC_TYPE(RTCRtpSender) *sender =
626        [[RTC_OBJC_TYPE(RTCRtpSender) alloc] initWithFactory:self.factory
627                                             nativeRtpSender:nativeSender];
628    [senders addObject:sender];
629  }
630  return senders;
631}
632
633- (NSArray<RTC_OBJC_TYPE(RTCRtpReceiver) *> *)receivers {
634  std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> nativeReceivers(
635      _peerConnection->GetReceivers());
636  NSMutableArray *receivers = [[NSMutableArray alloc] init];
637  for (const auto &nativeReceiver : nativeReceivers) {
638    RTC_OBJC_TYPE(RTCRtpReceiver) *receiver =
639        [[RTC_OBJC_TYPE(RTCRtpReceiver) alloc] initWithFactory:self.factory
640                                             nativeRtpReceiver:nativeReceiver];
641    [receivers addObject:receiver];
642  }
643  return receivers;
644}
645
646- (NSArray<RTC_OBJC_TYPE(RTCRtpTransceiver) *> *)transceivers {
647  std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceivers(
648      _peerConnection->GetTransceivers());
649  NSMutableArray *transceivers = [[NSMutableArray alloc] init];
650  for (const auto &nativeTransceiver : nativeTransceivers) {
651    RTC_OBJC_TYPE(RTCRtpTransceiver) *transceiver =
652        [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc] initWithFactory:self.factory
653                                             nativeRtpTransceiver:nativeTransceiver];
654    [transceivers addObject:transceiver];
655  }
656  return transceivers;
657}
658
659#pragma mark - Private
660
661+ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState:
662    (RTCSignalingState)state {
663  switch (state) {
664    case RTCSignalingStateStable:
665      return webrtc::PeerConnectionInterface::kStable;
666    case RTCSignalingStateHaveLocalOffer:
667      return webrtc::PeerConnectionInterface::kHaveLocalOffer;
668    case RTCSignalingStateHaveLocalPrAnswer:
669      return webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
670    case RTCSignalingStateHaveRemoteOffer:
671      return webrtc::PeerConnectionInterface::kHaveRemoteOffer;
672    case RTCSignalingStateHaveRemotePrAnswer:
673      return webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
674    case RTCSignalingStateClosed:
675      return webrtc::PeerConnectionInterface::kClosed;
676  }
677}
678
679+ (RTCSignalingState)signalingStateForNativeState:
680    (webrtc::PeerConnectionInterface::SignalingState)nativeState {
681  switch (nativeState) {
682    case webrtc::PeerConnectionInterface::kStable:
683      return RTCSignalingStateStable;
684    case webrtc::PeerConnectionInterface::kHaveLocalOffer:
685      return RTCSignalingStateHaveLocalOffer;
686    case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
687      return RTCSignalingStateHaveLocalPrAnswer;
688    case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
689      return RTCSignalingStateHaveRemoteOffer;
690    case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
691      return RTCSignalingStateHaveRemotePrAnswer;
692    case webrtc::PeerConnectionInterface::kClosed:
693      return RTCSignalingStateClosed;
694  }
695}
696
697+ (NSString *)stringForSignalingState:(RTCSignalingState)state {
698  switch (state) {
699    case RTCSignalingStateStable:
700      return @"STABLE";
701    case RTCSignalingStateHaveLocalOffer:
702      return @"HAVE_LOCAL_OFFER";
703    case RTCSignalingStateHaveLocalPrAnswer:
704      return @"HAVE_LOCAL_PRANSWER";
705    case RTCSignalingStateHaveRemoteOffer:
706      return @"HAVE_REMOTE_OFFER";
707    case RTCSignalingStateHaveRemotePrAnswer:
708      return @"HAVE_REMOTE_PRANSWER";
709    case RTCSignalingStateClosed:
710      return @"CLOSED";
711  }
712}
713
714+ (webrtc::PeerConnectionInterface::PeerConnectionState)nativeConnectionStateForState:
715        (RTCPeerConnectionState)state {
716  switch (state) {
717    case RTCPeerConnectionStateNew:
718      return webrtc::PeerConnectionInterface::PeerConnectionState::kNew;
719    case RTCPeerConnectionStateConnecting:
720      return webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting;
721    case RTCPeerConnectionStateConnected:
722      return webrtc::PeerConnectionInterface::PeerConnectionState::kConnected;
723    case RTCPeerConnectionStateFailed:
724      return webrtc::PeerConnectionInterface::PeerConnectionState::kFailed;
725    case RTCPeerConnectionStateDisconnected:
726      return webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected;
727    case RTCPeerConnectionStateClosed:
728      return webrtc::PeerConnectionInterface::PeerConnectionState::kClosed;
729  }
730}
731
732+ (RTCPeerConnectionState)connectionStateForNativeState:
733        (webrtc::PeerConnectionInterface::PeerConnectionState)nativeState {
734  switch (nativeState) {
735    case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
736      return RTCPeerConnectionStateNew;
737    case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
738      return RTCPeerConnectionStateConnecting;
739    case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
740      return RTCPeerConnectionStateConnected;
741    case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
742      return RTCPeerConnectionStateFailed;
743    case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
744      return RTCPeerConnectionStateDisconnected;
745    case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
746      return RTCPeerConnectionStateClosed;
747  }
748}
749
750+ (NSString *)stringForConnectionState:(RTCPeerConnectionState)state {
751  switch (state) {
752    case RTCPeerConnectionStateNew:
753      return @"NEW";
754    case RTCPeerConnectionStateConnecting:
755      return @"CONNECTING";
756    case RTCPeerConnectionStateConnected:
757      return @"CONNECTED";
758    case RTCPeerConnectionStateFailed:
759      return @"FAILED";
760    case RTCPeerConnectionStateDisconnected:
761      return @"DISCONNECTED";
762    case RTCPeerConnectionStateClosed:
763      return @"CLOSED";
764  }
765}
766
767+ (webrtc::PeerConnectionInterface::IceConnectionState)
768    nativeIceConnectionStateForState:(RTCIceConnectionState)state {
769  switch (state) {
770    case RTCIceConnectionStateNew:
771      return webrtc::PeerConnectionInterface::kIceConnectionNew;
772    case RTCIceConnectionStateChecking:
773      return webrtc::PeerConnectionInterface::kIceConnectionChecking;
774    case RTCIceConnectionStateConnected:
775      return webrtc::PeerConnectionInterface::kIceConnectionConnected;
776    case RTCIceConnectionStateCompleted:
777      return webrtc::PeerConnectionInterface::kIceConnectionCompleted;
778    case RTCIceConnectionStateFailed:
779      return webrtc::PeerConnectionInterface::kIceConnectionFailed;
780    case RTCIceConnectionStateDisconnected:
781      return webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
782    case RTCIceConnectionStateClosed:
783      return webrtc::PeerConnectionInterface::kIceConnectionClosed;
784    case RTCIceConnectionStateCount:
785      return webrtc::PeerConnectionInterface::kIceConnectionMax;
786  }
787}
788
789+ (RTCIceConnectionState)iceConnectionStateForNativeState:
790    (webrtc::PeerConnectionInterface::IceConnectionState)nativeState {
791  switch (nativeState) {
792    case webrtc::PeerConnectionInterface::kIceConnectionNew:
793      return RTCIceConnectionStateNew;
794    case webrtc::PeerConnectionInterface::kIceConnectionChecking:
795      return RTCIceConnectionStateChecking;
796    case webrtc::PeerConnectionInterface::kIceConnectionConnected:
797      return RTCIceConnectionStateConnected;
798    case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
799      return RTCIceConnectionStateCompleted;
800    case webrtc::PeerConnectionInterface::kIceConnectionFailed:
801      return RTCIceConnectionStateFailed;
802    case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
803      return RTCIceConnectionStateDisconnected;
804    case webrtc::PeerConnectionInterface::kIceConnectionClosed:
805      return RTCIceConnectionStateClosed;
806    case webrtc::PeerConnectionInterface::kIceConnectionMax:
807      return RTCIceConnectionStateCount;
808  }
809}
810
811+ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state {
812  switch (state) {
813    case RTCIceConnectionStateNew:
814      return @"NEW";
815    case RTCIceConnectionStateChecking:
816      return @"CHECKING";
817    case RTCIceConnectionStateConnected:
818      return @"CONNECTED";
819    case RTCIceConnectionStateCompleted:
820      return @"COMPLETED";
821    case RTCIceConnectionStateFailed:
822      return @"FAILED";
823    case RTCIceConnectionStateDisconnected:
824      return @"DISCONNECTED";
825    case RTCIceConnectionStateClosed:
826      return @"CLOSED";
827    case RTCIceConnectionStateCount:
828      return @"COUNT";
829  }
830}
831
832+ (webrtc::PeerConnectionInterface::IceGatheringState)
833    nativeIceGatheringStateForState:(RTCIceGatheringState)state {
834  switch (state) {
835    case RTCIceGatheringStateNew:
836      return webrtc::PeerConnectionInterface::kIceGatheringNew;
837    case RTCIceGatheringStateGathering:
838      return webrtc::PeerConnectionInterface::kIceGatheringGathering;
839    case RTCIceGatheringStateComplete:
840      return webrtc::PeerConnectionInterface::kIceGatheringComplete;
841  }
842}
843
844+ (RTCIceGatheringState)iceGatheringStateForNativeState:
845    (webrtc::PeerConnectionInterface::IceGatheringState)nativeState {
846  switch (nativeState) {
847    case webrtc::PeerConnectionInterface::kIceGatheringNew:
848      return RTCIceGatheringStateNew;
849    case webrtc::PeerConnectionInterface::kIceGatheringGathering:
850      return RTCIceGatheringStateGathering;
851    case webrtc::PeerConnectionInterface::kIceGatheringComplete:
852      return RTCIceGatheringStateComplete;
853  }
854}
855
856+ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state {
857  switch (state) {
858    case RTCIceGatheringStateNew:
859      return @"NEW";
860    case RTCIceGatheringStateGathering:
861      return @"GATHERING";
862    case RTCIceGatheringStateComplete:
863      return @"COMPLETE";
864  }
865}
866
867+ (webrtc::PeerConnectionInterface::StatsOutputLevel)
868    nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level {
869  switch (level) {
870    case RTCStatsOutputLevelStandard:
871      return webrtc::PeerConnectionInterface::kStatsOutputLevelStandard;
872    case RTCStatsOutputLevelDebug:
873      return webrtc::PeerConnectionInterface::kStatsOutputLevelDebug;
874  }
875}
876
877- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)nativePeerConnection {
878  return _peerConnection;
879}
880
881@end
882