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 "api/transport/media/media_transport_interface.h"
33#include "rtc_base/checks.h"
34#include "rtc_base/numerics/safe_conversions.h"
35
36NSString * 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
51  ~CreateSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
52
53  void OnSuccess(SessionDescriptionInterface *desc) override {
54    RTC_DCHECK(completion_handler_);
55    std::unique_ptr<webrtc::SessionDescriptionInterface> description =
56        std::unique_ptr<webrtc::SessionDescriptionInterface>(desc);
57    RTCSessionDescription* session =
58        [[RTCSessionDescription alloc] initWithNativeDescription:
59            description.get()];
60    completion_handler_(session, nil);
61    completion_handler_ = nil;
62  }
63
64  void OnFailure(RTCError error) override {
65    RTC_DCHECK(completion_handler_);
66    // TODO(hta): Add handling of error.type()
67    NSString *str = [NSString stringForStdString:error.message()];
68    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
89  ~SetSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
90
91  void OnSuccess() override {
92    RTC_DCHECK(completion_handler_);
93    completion_handler_(nil);
94    completion_handler_ = nil;
95  }
96
97  void OnFailure(RTCError error) override {
98    RTC_DCHECK(completion_handler_);
99    // TODO(hta): Add handling of error.type()
100    NSString *str = [NSString stringForStdString:error.message()];
101    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(
132    rtc::scoped_refptr<MediaStreamInterface> stream) {
133  RTCPeerConnection *peer_connection = peer_connection_;
134  RTCMediaStream *mediaStream =
135      [[RTCMediaStream alloc] initWithFactory:peer_connection.factory nativeMediaStream:stream];
136  [peer_connection.delegate peerConnection:peer_connection
137                              didAddStream:mediaStream];
138}
139
140void PeerConnectionDelegateAdapter::OnRemoveStream(
141    rtc::scoped_refptr<MediaStreamInterface> stream) {
142  RTCPeerConnection *peer_connection = peer_connection_;
143  RTCMediaStream *mediaStream =
144      [[RTCMediaStream alloc] initWithFactory:peer_connection.factory nativeMediaStream:stream];
145
146  [peer_connection.delegate peerConnection:peer_connection
147                           didRemoveStream:mediaStream];
148}
149
150void PeerConnectionDelegateAdapter::OnTrack(
151    rtc::scoped_refptr<RtpTransceiverInterface> nativeTransceiver) {
152  RTCPeerConnection *peer_connection = peer_connection_;
153  RTCRtpTransceiver *transceiver =
154      [[RTCRtpTransceiver alloc] initWithFactory:peer_connection.factory
155                            nativeRtpTransceiver:nativeTransceiver];
156  if ([peer_connection.delegate
157          respondsToSelector:@selector(peerConnection:didStartReceivingOnTransceiver:)]) {
158    [peer_connection.delegate peerConnection:peer_connection
159              didStartReceivingOnTransceiver:transceiver];
160  }
161}
162
163void PeerConnectionDelegateAdapter::OnDataChannel(
164    rtc::scoped_refptr<DataChannelInterface> data_channel) {
165  RTCPeerConnection *peer_connection = peer_connection_;
166  RTCDataChannel *dataChannel = [[RTCDataChannel alloc] initWithFactory:peer_connection.factory
167                                                      nativeDataChannel:data_channel];
168  [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) {
179  RTCIceConnectionState state = [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 = [RTCPeerConnection iceConnectionStateForNativeState:new_state];
188    [peer_connection_.delegate peerConnection:peer_connection_
189        didChangeStandardizedIceConnectionState:state];
190  }
191}
192
193void 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  }
200}
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}
219
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
236void PeerConnectionDelegateAdapter::OnIceSelectedCandidatePairChanged(
237    const cricket::CandidatePairChangeEvent &event) {
238  const auto &selected_pair = event.selected_candidate_pair;
239  auto local_candidate_wrapper = std::make_unique<JsepIceCandidate>(
240      selected_pair.local_candidate().transport_name(), -1, selected_pair.local_candidate());
241  RTCIceCandidate *local_candidate =
242      [[RTCIceCandidate alloc] initWithNativeCandidate:local_candidate_wrapper.release()];
243  auto remote_candidate_wrapper = std::make_unique<JsepIceCandidate>(
244      selected_pair.remote_candidate().transport_name(), -1, selected_pair.remote_candidate());
245  RTCIceCandidate *remote_candidate =
246      [[RTCIceCandidate alloc] initWithNativeCandidate:remote_candidate_wrapper.release()];
247  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
260void PeerConnectionDelegateAdapter::OnAddTrack(
261    rtc::scoped_refptr<RtpReceiverInterface> receiver,
262    const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) {
263  RTCPeerConnection *peer_connection = peer_connection_;
264  if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:
265                                                             didAddReceiver:streams:)]) {
266    NSMutableArray *mediaStreams = [NSMutableArray arrayWithCapacity:streams.size()];
267    for (const auto &nativeStream : streams) {
268      RTCMediaStream *mediaStream = [[RTCMediaStream alloc] initWithFactory:peer_connection.factory
269                                                          nativeMediaStream:nativeStream];
270      [mediaStreams addObject:mediaStream];
271    }
272    RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory
273                                                        nativeRtpReceiver:receiver];
274
275    [peer_connection.delegate peerConnection:peer_connection
276                              didAddReceiver:rtpReceiver
277                                     streams:mediaStreams];
278  }
279}
280
281void PeerConnectionDelegateAdapter::OnRemoveTrack(
282    rtc::scoped_refptr<RtpReceiverInterface> receiver) {
283  RTCPeerConnection *peer_connection = peer_connection_;
284  if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:didRemoveReceiver:)]) {
285    RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory
286                                                        nativeRtpReceiver:receiver];
287    [peer_connection.delegate peerConnection:peer_connection didRemoveReceiver:rtpReceiver];
288  }
289}
290
291}  // namespace webrtc
292
293@implementation RTCPeerConnection {
294  RTCPeerConnectionFactory *_factory;
295  NSMutableArray<RTCMediaStream *> *_localStreams;
296  std::unique_ptr<webrtc::PeerConnectionDelegateAdapter> _observer;
297  rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
298  std::unique_ptr<webrtc::MediaConstraints> _nativeConstraints;
299  BOOL _hasStartedRtcEventLog;
300}
301
302@synthesize delegate = _delegate;
303@synthesize factory = _factory;
304
305- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
306                  configuration:(RTCConfiguration *)configuration
307                    constraints:(RTCMediaConstraints *)constraints
308                       delegate:(id<RTCPeerConnectionDelegate>)delegate {
309  NSParameterAssert(factory);
310  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());
327  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
328      [configuration createNativeConfiguration]);
329  if (!config) {
330    return nil;
331  }
332  if (self = [super init]) {
333    _observer.reset(new webrtc::PeerConnectionDelegateAdapter(self));
334    _nativeConstraints = constraints.nativeConstraints;
335    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
341    if (!_peerConnection) {
342      return nil;
343    }
344    _factory = factory;
345    _localStreams = [[NSMutableArray alloc] init];
346    _delegate = delegate;
347  }
348  return self;
349}
350
351- (NSArray<RTCMediaStream *> *)localStreams {
352  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
381- (RTCPeerConnectionState)connectionState {
382  return [[self class] connectionStateForNativeState:_peerConnection->peer_connection_state()];
383}
384
385- (RTCIceGatheringState)iceGatheringState {
386  return [[self class] iceGatheringStateForNativeState:
387      _peerConnection->ice_gathering_state()];
388}
389
390- (BOOL)setConfiguration:(RTCConfiguration *)configuration {
391  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
392      [configuration createNativeConfiguration]);
393  if (!config) {
394    return NO;
395  }
396  CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(),
397                                      config.get());
398  return _peerConnection->SetConfiguration(*config).ok();
399}
400
401- (RTCConfiguration *)configuration {
402  webrtc::PeerConnectionInterface::RTCConfiguration config =
403    _peerConnection->GetConfiguration();
404  return [[RTCConfiguration alloc] initWithNativeConfiguration:config];
405}
406
407- (void)close {
408  _peerConnection->Close();
409}
410
411- (void)addIceCandidate:(RTCIceCandidate *)candidate {
412  std::unique_ptr<const webrtc::IceCandidateInterface> iceCandidate(
413      candidate.nativeCandidate);
414  _peerConnection->AddIceCandidate(iceCandidate.get());
415}
416
417- (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
433- (void)addStream:(RTCMediaStream *)stream {
434  if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
435    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
446- (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]);
450  }
451  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenderOrError =
452      _peerConnection->AddTrack(track.nativeTrack, nativeStreamIds);
453  if (!nativeSenderOrError.ok()) {
454    RTCLogError(@"Failed to add track %@: %s", track, nativeSenderOrError.error().message());
455    return nil;
456  }
457  return [[RTCRtpSender alloc] initWithFactory:self.factory
458                               nativeRtpSender:nativeSenderOrError.MoveValue()];
459}
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  }
482  return [[RTCRtpTransceiver alloc] initWithFactory:self.factory
483                               nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
484}
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  }
501  return [[RTCRtpTransceiver alloc] initWithFactory:self.factory
502                               nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
503}
504
505- (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));
512  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
513  CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
514
515  _peerConnection->CreateOffer(observer, options);
516}
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));
525  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
526  CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
527
528  _peerConnection->CreateAnswer(observer, options);
529}
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
547- (BOOL)setBweMinBitrateBps:(nullable NSNumber *)minBitrateBps
548          currentBitrateBps:(nullable NSNumber *)currentBitrateBps
549              maxBitrateBps:(nullable NSNumber *)maxBitrateBps {
550  webrtc::PeerConnectionInterface::BitrateParameters params;
551  if (minBitrateBps != nil) {
552    params.min_bitrate_bps = absl::optional<int>(minBitrateBps.intValue);
553  }
554  if (currentBitrateBps != nil) {
555    params.current_bitrate_bps = absl::optional<int>(currentBitrateBps.intValue);
556  }
557  if (maxBitrateBps != nil) {
558    params.max_bitrate_bps = absl::optional<int>(maxBitrateBps.intValue);
559  }
560  return _peerConnection->SetBitrate(params).ok();
561}
562
563- (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  }
572  FILE *f = fopen(filePath.UTF8String, "wb");
573  if (!f) {
574    RTCLogError(@"Error opening file: %@. Error: %d", filePath, errno);
575    return NO;
576  }
577  // 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(
582      std::make_unique<webrtc::RtcEventLogOutputFile>(f, max_size));
583  return _hasStartedRtcEventLog;
584}
585
586- (void)stopRtcEventLog {
587  _peerConnection->StopRtcEventLog();
588  _hasStartedRtcEventLog = NO;
589}
590
591- (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 ?
598      [[RTCRtpSender alloc] initWithFactory:self.factory nativeRtpSender:nativeSender] :
599      nil;
600}
601
602- (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 =
608        [[RTCRtpSender alloc] initWithFactory:self.factory nativeRtpSender:nativeSender];
609    [senders addObject:sender];
610  }
611  return senders;
612}
613
614- (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 =
620        [[RTCRtpReceiver alloc] initWithFactory:self.factory nativeRtpReceiver:nativeReceiver];
621    [receivers addObject:receiver];
622  }
623  return receivers;
624}
625
626- (NSArray<RTCRtpTransceiver *> *)transceivers {
627  std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceivers(
628      _peerConnection->GetTransceivers());
629  NSMutableArray *transceivers = [[NSMutableArray alloc] init];
630  for (const auto &nativeTransceiver : nativeTransceivers) {
631    RTCRtpTransceiver *transceiver = [[RTCRtpTransceiver alloc] initWithFactory:self.factory
632                                                           nativeRtpTransceiver:nativeTransceiver];
633    [transceivers addObject:transceiver];
634  }
635  return transceivers;
636}
637
638#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
693+ (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
746+ (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;
763    case RTCIceConnectionStateCount:
764      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:
786      return RTCIceConnectionStateCount;
787  }
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";
806    case RTCIceConnectionStateCount:
807      return @"COUNT";
808  }
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
856- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)nativePeerConnection {
857  return _peerConnection;
858}
859
860@end
861