• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  const webrtc::SessionDescriptionInterface *description =
362      _peerConnection->local_description();
363  return description ?
364      [[RTC_OBJC_TYPE(RTCSessionDescription) alloc] initWithNativeDescription:description] :
365      nil;
366}
367
368- (RTC_OBJC_TYPE(RTCSessionDescription) *)remoteDescription {
369  const webrtc::SessionDescriptionInterface *description =
370      _peerConnection->remote_description();
371  return description ?
372      [[RTC_OBJC_TYPE(RTCSessionDescription) alloc] initWithNativeDescription:description] :
373      nil;
374}
375
376- (RTCSignalingState)signalingState {
377  return [[self class]
378      signalingStateForNativeState:_peerConnection->signaling_state()];
379}
380
381- (RTCIceConnectionState)iceConnectionState {
382  return [[self class] iceConnectionStateForNativeState:
383      _peerConnection->ice_connection_state()];
384}
385
386- (RTCPeerConnectionState)connectionState {
387  return [[self class] connectionStateForNativeState:_peerConnection->peer_connection_state()];
388}
389
390- (RTCIceGatheringState)iceGatheringState {
391  return [[self class] iceGatheringStateForNativeState:
392      _peerConnection->ice_gathering_state()];
393}
394
395- (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCConfiguration) *)configuration {
396  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
397      [configuration createNativeConfiguration]);
398  if (!config) {
399    return NO;
400  }
401  CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(),
402                                      config.get());
403  return _peerConnection->SetConfiguration(*config).ok();
404}
405
406- (RTC_OBJC_TYPE(RTCConfiguration) *)configuration {
407  webrtc::PeerConnectionInterface::RTCConfiguration config =
408    _peerConnection->GetConfiguration();
409  return [[RTC_OBJC_TYPE(RTCConfiguration) alloc] initWithNativeConfiguration:config];
410}
411
412- (void)close {
413  _peerConnection->Close();
414}
415
416- (void)addIceCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)candidate {
417  std::unique_ptr<const webrtc::IceCandidateInterface> iceCandidate(
418      candidate.nativeCandidate);
419  _peerConnection->AddIceCandidate(iceCandidate.get());
420}
421
422- (void)removeIceCandidates:(NSArray<RTC_OBJC_TYPE(RTCIceCandidate) *> *)iceCandidates {
423  std::vector<cricket::Candidate> candidates;
424  for (RTC_OBJC_TYPE(RTCIceCandidate) * iceCandidate in iceCandidates) {
425    std::unique_ptr<const webrtc::IceCandidateInterface> candidate(
426        iceCandidate.nativeCandidate);
427    if (candidate) {
428      candidates.push_back(candidate->candidate());
429      // Need to fill the transport name from the sdp_mid.
430      candidates.back().set_transport_name(candidate->sdp_mid());
431    }
432  }
433  if (!candidates.empty()) {
434    _peerConnection->RemoveIceCandidates(candidates);
435  }
436}
437
438- (void)addStream:(RTC_OBJC_TYPE(RTCMediaStream) *)stream {
439  if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
440    RTCLogError(@"Failed to add stream: %@", stream);
441    return;
442  }
443  [_localStreams addObject:stream];
444}
445
446- (void)removeStream:(RTC_OBJC_TYPE(RTCMediaStream) *)stream {
447  _peerConnection->RemoveStream(stream.nativeMediaStream);
448  [_localStreams removeObject:stream];
449}
450
451- (RTC_OBJC_TYPE(RTCRtpSender) *)addTrack:(RTC_OBJC_TYPE(RTCMediaStreamTrack) *)track
452                                streamIds:(NSArray<NSString *> *)streamIds {
453  std::vector<std::string> nativeStreamIds;
454  for (NSString *streamId in streamIds) {
455    nativeStreamIds.push_back([streamId UTF8String]);
456  }
457  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenderOrError =
458      _peerConnection->AddTrack(track.nativeTrack, nativeStreamIds);
459  if (!nativeSenderOrError.ok()) {
460    RTCLogError(@"Failed to add track %@: %s", track, nativeSenderOrError.error().message());
461    return nil;
462  }
463  return [[RTC_OBJC_TYPE(RTCRtpSender) alloc] initWithFactory:self.factory
464                                              nativeRtpSender:nativeSenderOrError.MoveValue()];
465}
466
467- (BOOL)removeTrack:(RTC_OBJC_TYPE(RTCRtpSender) *)sender {
468  bool result = _peerConnection->RemoveTrack(sender.nativeRtpSender);
469  if (!result) {
470    RTCLogError(@"Failed to remote track %@", sender);
471  }
472  return result;
473}
474
475- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)addTransceiverWithTrack:
476    (RTC_OBJC_TYPE(RTCMediaStreamTrack) *)track {
477  return [self addTransceiverWithTrack:track
478                                  init:[[RTC_OBJC_TYPE(RTCRtpTransceiverInit) alloc] init]];
479}
480
481- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)
482    addTransceiverWithTrack:(RTC_OBJC_TYPE(RTCMediaStreamTrack) *)track
483                       init:(RTC_OBJC_TYPE(RTCRtpTransceiverInit) *)init {
484  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
485      _peerConnection->AddTransceiver(track.nativeTrack, init.nativeInit);
486  if (!nativeTransceiverOrError.ok()) {
487    RTCLogError(
488        @"Failed to add transceiver %@: %s", track, nativeTransceiverOrError.error().message());
489    return nil;
490  }
491  return [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc]
492           initWithFactory:self.factory
493      nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
494}
495
496- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)addTransceiverOfType:(RTCRtpMediaType)mediaType {
497  return [self addTransceiverOfType:mediaType
498                               init:[[RTC_OBJC_TYPE(RTCRtpTransceiverInit) alloc] init]];
499}
500
501- (RTC_OBJC_TYPE(RTCRtpTransceiver) *)addTransceiverOfType:(RTCRtpMediaType)mediaType
502                                                      init:(RTC_OBJC_TYPE(RTCRtpTransceiverInit) *)
503                                                               init {
504  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
505      _peerConnection->AddTransceiver(
506          [RTC_OBJC_TYPE(RTCRtpReceiver) nativeMediaTypeForMediaType:mediaType], init.nativeInit);
507  if (!nativeTransceiverOrError.ok()) {
508    RTCLogError(@"Failed to add transceiver %@: %s",
509                [RTC_OBJC_TYPE(RTCRtpReceiver) stringForMediaType:mediaType],
510                nativeTransceiverOrError.error().message());
511    return nil;
512  }
513  return [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc]
514           initWithFactory:self.factory
515      nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
516}
517
518- (void)offerForConstraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints
519          completionHandler:(void (^)(RTC_OBJC_TYPE(RTCSessionDescription) * sessionDescription,
520                                      NSError *error))completionHandler {
521  rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
522      observer(new rtc::RefCountedObject
523          <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
524  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
525  CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
526
527  _peerConnection->CreateOffer(observer, options);
528}
529
530- (void)answerForConstraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints
531           completionHandler:(void (^)(RTC_OBJC_TYPE(RTCSessionDescription) * sessionDescription,
532                                       NSError *error))completionHandler {
533  rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
534      observer(new rtc::RefCountedObject
535          <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
536  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options;
537  CopyConstraintsIntoOfferAnswerOptions(constraints.nativeConstraints.get(), &options);
538
539  _peerConnection->CreateAnswer(observer, options);
540}
541
542- (void)setLocalDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
543          completionHandler:(void (^)(NSError *error))completionHandler {
544  rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
545      new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
546          completionHandler));
547  _peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
548}
549
550- (void)setRemoteDescription:(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->SetRemoteDescription(observer, sdp.nativeDescription);
556}
557
558- (BOOL)setBweMinBitrateBps:(nullable NSNumber *)minBitrateBps
559          currentBitrateBps:(nullable NSNumber *)currentBitrateBps
560              maxBitrateBps:(nullable NSNumber *)maxBitrateBps {
561  webrtc::BitrateSettings params;
562  if (minBitrateBps != nil) {
563    params.min_bitrate_bps = absl::optional<int>(minBitrateBps.intValue);
564  }
565  if (currentBitrateBps != nil) {
566    params.start_bitrate_bps = absl::optional<int>(currentBitrateBps.intValue);
567  }
568  if (maxBitrateBps != nil) {
569    params.max_bitrate_bps = absl::optional<int>(maxBitrateBps.intValue);
570  }
571  return _peerConnection->SetBitrate(params).ok();
572}
573
574- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
575                      maxSizeInBytes:(int64_t)maxSizeInBytes {
576  RTC_DCHECK(filePath.length);
577  RTC_DCHECK_GT(maxSizeInBytes, 0);
578  RTC_DCHECK(!_hasStartedRtcEventLog);
579  if (_hasStartedRtcEventLog) {
580    RTCLogError(@"Event logging already started.");
581    return NO;
582  }
583  FILE *f = fopen(filePath.UTF8String, "wb");
584  if (!f) {
585    RTCLogError(@"Error opening file: %@. Error: %d", filePath, errno);
586    return NO;
587  }
588  // TODO(eladalon): It would be better to not allow negative values into PC.
589  const size_t max_size = (maxSizeInBytes < 0) ? webrtc::RtcEventLog::kUnlimitedOutput :
590                                                 rtc::saturated_cast<size_t>(maxSizeInBytes);
591
592  _hasStartedRtcEventLog = _peerConnection->StartRtcEventLog(
593      std::make_unique<webrtc::RtcEventLogOutputFile>(f, max_size));
594  return _hasStartedRtcEventLog;
595}
596
597- (void)stopRtcEventLog {
598  _peerConnection->StopRtcEventLog();
599  _hasStartedRtcEventLog = NO;
600}
601
602- (RTC_OBJC_TYPE(RTCRtpSender) *)senderWithKind:(NSString *)kind streamId:(NSString *)streamId {
603  std::string nativeKind = [NSString stdStringForString:kind];
604  std::string nativeStreamId = [NSString stdStringForString:streamId];
605  rtc::scoped_refptr<webrtc::RtpSenderInterface> nativeSender(
606      _peerConnection->CreateSender(nativeKind, nativeStreamId));
607  return nativeSender ? [[RTC_OBJC_TYPE(RTCRtpSender) alloc] initWithFactory:self.factory
608                                                             nativeRtpSender:nativeSender] :
609                        nil;
610}
611
612- (NSArray<RTC_OBJC_TYPE(RTCRtpSender) *> *)senders {
613  std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenders(
614      _peerConnection->GetSenders());
615  NSMutableArray *senders = [[NSMutableArray alloc] init];
616  for (const auto &nativeSender : nativeSenders) {
617    RTC_OBJC_TYPE(RTCRtpSender) *sender =
618        [[RTC_OBJC_TYPE(RTCRtpSender) alloc] initWithFactory:self.factory
619                                             nativeRtpSender:nativeSender];
620    [senders addObject:sender];
621  }
622  return senders;
623}
624
625- (NSArray<RTC_OBJC_TYPE(RTCRtpReceiver) *> *)receivers {
626  std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> nativeReceivers(
627      _peerConnection->GetReceivers());
628  NSMutableArray *receivers = [[NSMutableArray alloc] init];
629  for (const auto &nativeReceiver : nativeReceivers) {
630    RTC_OBJC_TYPE(RTCRtpReceiver) *receiver =
631        [[RTC_OBJC_TYPE(RTCRtpReceiver) alloc] initWithFactory:self.factory
632                                             nativeRtpReceiver:nativeReceiver];
633    [receivers addObject:receiver];
634  }
635  return receivers;
636}
637
638- (NSArray<RTC_OBJC_TYPE(RTCRtpTransceiver) *> *)transceivers {
639  std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceivers(
640      _peerConnection->GetTransceivers());
641  NSMutableArray *transceivers = [[NSMutableArray alloc] init];
642  for (const auto &nativeTransceiver : nativeTransceivers) {
643    RTC_OBJC_TYPE(RTCRtpTransceiver) *transceiver =
644        [[RTC_OBJC_TYPE(RTCRtpTransceiver) alloc] initWithFactory:self.factory
645                                             nativeRtpTransceiver:nativeTransceiver];
646    [transceivers addObject:transceiver];
647  }
648  return transceivers;
649}
650
651#pragma mark - Private
652
653+ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState:
654    (RTCSignalingState)state {
655  switch (state) {
656    case RTCSignalingStateStable:
657      return webrtc::PeerConnectionInterface::kStable;
658    case RTCSignalingStateHaveLocalOffer:
659      return webrtc::PeerConnectionInterface::kHaveLocalOffer;
660    case RTCSignalingStateHaveLocalPrAnswer:
661      return webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
662    case RTCSignalingStateHaveRemoteOffer:
663      return webrtc::PeerConnectionInterface::kHaveRemoteOffer;
664    case RTCSignalingStateHaveRemotePrAnswer:
665      return webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
666    case RTCSignalingStateClosed:
667      return webrtc::PeerConnectionInterface::kClosed;
668  }
669}
670
671+ (RTCSignalingState)signalingStateForNativeState:
672    (webrtc::PeerConnectionInterface::SignalingState)nativeState {
673  switch (nativeState) {
674    case webrtc::PeerConnectionInterface::kStable:
675      return RTCSignalingStateStable;
676    case webrtc::PeerConnectionInterface::kHaveLocalOffer:
677      return RTCSignalingStateHaveLocalOffer;
678    case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
679      return RTCSignalingStateHaveLocalPrAnswer;
680    case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
681      return RTCSignalingStateHaveRemoteOffer;
682    case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
683      return RTCSignalingStateHaveRemotePrAnswer;
684    case webrtc::PeerConnectionInterface::kClosed:
685      return RTCSignalingStateClosed;
686  }
687}
688
689+ (NSString *)stringForSignalingState:(RTCSignalingState)state {
690  switch (state) {
691    case RTCSignalingStateStable:
692      return @"STABLE";
693    case RTCSignalingStateHaveLocalOffer:
694      return @"HAVE_LOCAL_OFFER";
695    case RTCSignalingStateHaveLocalPrAnswer:
696      return @"HAVE_LOCAL_PRANSWER";
697    case RTCSignalingStateHaveRemoteOffer:
698      return @"HAVE_REMOTE_OFFER";
699    case RTCSignalingStateHaveRemotePrAnswer:
700      return @"HAVE_REMOTE_PRANSWER";
701    case RTCSignalingStateClosed:
702      return @"CLOSED";
703  }
704}
705
706+ (webrtc::PeerConnectionInterface::PeerConnectionState)nativeConnectionStateForState:
707        (RTCPeerConnectionState)state {
708  switch (state) {
709    case RTCPeerConnectionStateNew:
710      return webrtc::PeerConnectionInterface::PeerConnectionState::kNew;
711    case RTCPeerConnectionStateConnecting:
712      return webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting;
713    case RTCPeerConnectionStateConnected:
714      return webrtc::PeerConnectionInterface::PeerConnectionState::kConnected;
715    case RTCPeerConnectionStateFailed:
716      return webrtc::PeerConnectionInterface::PeerConnectionState::kFailed;
717    case RTCPeerConnectionStateDisconnected:
718      return webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected;
719    case RTCPeerConnectionStateClosed:
720      return webrtc::PeerConnectionInterface::PeerConnectionState::kClosed;
721  }
722}
723
724+ (RTCPeerConnectionState)connectionStateForNativeState:
725        (webrtc::PeerConnectionInterface::PeerConnectionState)nativeState {
726  switch (nativeState) {
727    case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
728      return RTCPeerConnectionStateNew;
729    case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
730      return RTCPeerConnectionStateConnecting;
731    case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
732      return RTCPeerConnectionStateConnected;
733    case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
734      return RTCPeerConnectionStateFailed;
735    case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
736      return RTCPeerConnectionStateDisconnected;
737    case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
738      return RTCPeerConnectionStateClosed;
739  }
740}
741
742+ (NSString *)stringForConnectionState:(RTCPeerConnectionState)state {
743  switch (state) {
744    case RTCPeerConnectionStateNew:
745      return @"NEW";
746    case RTCPeerConnectionStateConnecting:
747      return @"CONNECTING";
748    case RTCPeerConnectionStateConnected:
749      return @"CONNECTED";
750    case RTCPeerConnectionStateFailed:
751      return @"FAILED";
752    case RTCPeerConnectionStateDisconnected:
753      return @"DISCONNECTED";
754    case RTCPeerConnectionStateClosed:
755      return @"CLOSED";
756  }
757}
758
759+ (webrtc::PeerConnectionInterface::IceConnectionState)
760    nativeIceConnectionStateForState:(RTCIceConnectionState)state {
761  switch (state) {
762    case RTCIceConnectionStateNew:
763      return webrtc::PeerConnectionInterface::kIceConnectionNew;
764    case RTCIceConnectionStateChecking:
765      return webrtc::PeerConnectionInterface::kIceConnectionChecking;
766    case RTCIceConnectionStateConnected:
767      return webrtc::PeerConnectionInterface::kIceConnectionConnected;
768    case RTCIceConnectionStateCompleted:
769      return webrtc::PeerConnectionInterface::kIceConnectionCompleted;
770    case RTCIceConnectionStateFailed:
771      return webrtc::PeerConnectionInterface::kIceConnectionFailed;
772    case RTCIceConnectionStateDisconnected:
773      return webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
774    case RTCIceConnectionStateClosed:
775      return webrtc::PeerConnectionInterface::kIceConnectionClosed;
776    case RTCIceConnectionStateCount:
777      return webrtc::PeerConnectionInterface::kIceConnectionMax;
778  }
779}
780
781+ (RTCIceConnectionState)iceConnectionStateForNativeState:
782    (webrtc::PeerConnectionInterface::IceConnectionState)nativeState {
783  switch (nativeState) {
784    case webrtc::PeerConnectionInterface::kIceConnectionNew:
785      return RTCIceConnectionStateNew;
786    case webrtc::PeerConnectionInterface::kIceConnectionChecking:
787      return RTCIceConnectionStateChecking;
788    case webrtc::PeerConnectionInterface::kIceConnectionConnected:
789      return RTCIceConnectionStateConnected;
790    case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
791      return RTCIceConnectionStateCompleted;
792    case webrtc::PeerConnectionInterface::kIceConnectionFailed:
793      return RTCIceConnectionStateFailed;
794    case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
795      return RTCIceConnectionStateDisconnected;
796    case webrtc::PeerConnectionInterface::kIceConnectionClosed:
797      return RTCIceConnectionStateClosed;
798    case webrtc::PeerConnectionInterface::kIceConnectionMax:
799      return RTCIceConnectionStateCount;
800  }
801}
802
803+ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state {
804  switch (state) {
805    case RTCIceConnectionStateNew:
806      return @"NEW";
807    case RTCIceConnectionStateChecking:
808      return @"CHECKING";
809    case RTCIceConnectionStateConnected:
810      return @"CONNECTED";
811    case RTCIceConnectionStateCompleted:
812      return @"COMPLETED";
813    case RTCIceConnectionStateFailed:
814      return @"FAILED";
815    case RTCIceConnectionStateDisconnected:
816      return @"DISCONNECTED";
817    case RTCIceConnectionStateClosed:
818      return @"CLOSED";
819    case RTCIceConnectionStateCount:
820      return @"COUNT";
821  }
822}
823
824+ (webrtc::PeerConnectionInterface::IceGatheringState)
825    nativeIceGatheringStateForState:(RTCIceGatheringState)state {
826  switch (state) {
827    case RTCIceGatheringStateNew:
828      return webrtc::PeerConnectionInterface::kIceGatheringNew;
829    case RTCIceGatheringStateGathering:
830      return webrtc::PeerConnectionInterface::kIceGatheringGathering;
831    case RTCIceGatheringStateComplete:
832      return webrtc::PeerConnectionInterface::kIceGatheringComplete;
833  }
834}
835
836+ (RTCIceGatheringState)iceGatheringStateForNativeState:
837    (webrtc::PeerConnectionInterface::IceGatheringState)nativeState {
838  switch (nativeState) {
839    case webrtc::PeerConnectionInterface::kIceGatheringNew:
840      return RTCIceGatheringStateNew;
841    case webrtc::PeerConnectionInterface::kIceGatheringGathering:
842      return RTCIceGatheringStateGathering;
843    case webrtc::PeerConnectionInterface::kIceGatheringComplete:
844      return RTCIceGatheringStateComplete;
845  }
846}
847
848+ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state {
849  switch (state) {
850    case RTCIceGatheringStateNew:
851      return @"NEW";
852    case RTCIceGatheringStateGathering:
853      return @"GATHERING";
854    case RTCIceGatheringStateComplete:
855      return @"COMPLETE";
856  }
857}
858
859+ (webrtc::PeerConnectionInterface::StatsOutputLevel)
860    nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level {
861  switch (level) {
862    case RTCStatsOutputLevelStandard:
863      return webrtc::PeerConnectionInterface::kStatsOutputLevelStandard;
864    case RTCStatsOutputLevelDebug:
865      return webrtc::PeerConnectionInterface::kStatsOutputLevelDebug;
866  }
867}
868
869- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)nativePeerConnection {
870  return _peerConnection;
871}
872
873@end
874