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