blob: 657ba57e26a50f58b389c47d14b665580d639793 [file] [log] [blame]
hjonf396f602016-02-11 16:19:06 -08001/*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import "webrtc/api/objc/RTCPeerConnection.h"
12
13#include "webrtc/base/checks.h"
14
15#import "webrtc/api/objc/RTCPeerConnection+Private.h"
16#import "webrtc/api/objc/RTCConfiguration+Private.h"
17#import "webrtc/api/objc/RTCDataChannel+Private.h"
18#import "webrtc/api/objc/RTCIceCandidate+Private.h"
19#import "webrtc/api/objc/RTCMediaConstraints+Private.h"
20#import "webrtc/api/objc/RTCMediaStream+Private.h"
21#import "webrtc/api/objc/RTCPeerConnectionFactory+Private.h"
skvlad79b4b872016-04-08 17:28:55 -070022#import "webrtc/api/objc/RTCRtpSender+Private.h"
hjonf396f602016-02-11 16:19:06 -080023#import "webrtc/api/objc/RTCSessionDescription+Private.h"
24#import "webrtc/api/objc/RTCStatsReport+Private.h"
25#import "webrtc/base/objc/RTCLogging.h"
26#import "webrtc/base/objc/NSString+StdString.h"
27
28NSString * const kRTCPeerConnectionErrorDomain =
29 @"org.webrtc.RTCPeerConnection";
30int const kRTCPeerConnnectionSessionDescriptionError = -1;
31
32namespace webrtc {
33
34class CreateSessionDescriptionObserverAdapter
35 : public CreateSessionDescriptionObserver {
36 public:
37 CreateSessionDescriptionObserverAdapter(
38 void (^completionHandler)(RTCSessionDescription *sessionDescription,
39 NSError *error)) {
40 completion_handler_ = completionHandler;
41 }
42
43 ~CreateSessionDescriptionObserverAdapter() {
44 completion_handler_ = nil;
45 }
46
47 void OnSuccess(SessionDescriptionInterface *desc) override {
48 RTC_DCHECK(completion_handler_);
49 rtc::scoped_ptr<webrtc::SessionDescriptionInterface> description =
50 rtc::scoped_ptr<webrtc::SessionDescriptionInterface>(desc);
51 RTCSessionDescription* session =
52 [[RTCSessionDescription alloc] initWithNativeDescription:
53 description.get()];
54 completion_handler_(session, nil);
55 completion_handler_ = nil;
56 }
57
58 void OnFailure(const std::string& error) override {
59 RTC_DCHECK(completion_handler_);
60 NSString* str = [NSString stringForStdString:error];
61 NSError* err =
62 [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
63 code:kRTCPeerConnnectionSessionDescriptionError
64 userInfo:@{ NSLocalizedDescriptionKey : str }];
65 completion_handler_(nil, err);
66 completion_handler_ = nil;
67 }
68
69 private:
70 void (^completion_handler_)
71 (RTCSessionDescription *sessionDescription, NSError *error);
72};
73
74class SetSessionDescriptionObserverAdapter :
75 public SetSessionDescriptionObserver {
76 public:
77 SetSessionDescriptionObserverAdapter(void (^completionHandler)
78 (NSError *error)) {
79 completion_handler_ = completionHandler;
80 }
81
82 ~SetSessionDescriptionObserverAdapter() {
83 completion_handler_ = nil;
84 }
85
86 void OnSuccess() override {
87 RTC_DCHECK(completion_handler_);
88 completion_handler_(nil);
89 completion_handler_ = nil;
90 }
91
92 void OnFailure(const std::string& error) override {
93 RTC_DCHECK(completion_handler_);
94 NSString* str = [NSString stringForStdString:error];
95 NSError* err =
96 [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
97 code:kRTCPeerConnnectionSessionDescriptionError
98 userInfo:@{ NSLocalizedDescriptionKey : str }];
99 completion_handler_(err);
100 completion_handler_ = nil;
101 }
102
103 private:
104 void (^completion_handler_)(NSError *error);
105};
106
107PeerConnectionDelegateAdapter::PeerConnectionDelegateAdapter(
108 RTCPeerConnection *peerConnection) {
109 peer_connection_ = peerConnection;
110}
111
112PeerConnectionDelegateAdapter::~PeerConnectionDelegateAdapter() {
113 peer_connection_ = nil;
114}
115
116void PeerConnectionDelegateAdapter::OnSignalingChange(
117 PeerConnectionInterface::SignalingState new_state) {
118 RTCSignalingState state =
119 [[RTCPeerConnection class] signalingStateForNativeState:new_state];
120 RTCPeerConnection *peer_connection = peer_connection_;
121 [peer_connection.delegate peerConnection:peer_connection
122 didChangeSignalingState:state];
123}
124
125void PeerConnectionDelegateAdapter::OnAddStream(
126 MediaStreamInterface *stream) {
127 RTCMediaStream *mediaStream =
128 [[RTCMediaStream alloc] initWithNativeMediaStream:stream];
129 RTCPeerConnection *peer_connection = peer_connection_;
130 [peer_connection.delegate peerConnection:peer_connection
131 didAddStream:mediaStream];
132}
133
134void PeerConnectionDelegateAdapter::OnRemoveStream(
135 MediaStreamInterface *stream) {
136 RTCMediaStream *mediaStream =
137 [[RTCMediaStream alloc] initWithNativeMediaStream:stream];
138 RTCPeerConnection *peer_connection = peer_connection_;
139 [peer_connection.delegate peerConnection:peer_connection
140 didRemoveStream:mediaStream];
141}
142
143void PeerConnectionDelegateAdapter::OnDataChannel(
144 DataChannelInterface *data_channel) {
145 RTCDataChannel *dataChannel =
146 [[RTCDataChannel alloc] initWithNativeDataChannel:data_channel];
147 RTCPeerConnection *peer_connection = peer_connection_;
148 [peer_connection.delegate peerConnection:peer_connection
149 didOpenDataChannel:dataChannel];
150}
151
152void PeerConnectionDelegateAdapter::OnRenegotiationNeeded() {
153 RTCPeerConnection *peer_connection = peer_connection_;
154 [peer_connection.delegate peerConnectionShouldNegotiate:peer_connection];
155}
156
157void PeerConnectionDelegateAdapter::OnIceConnectionChange(
158 PeerConnectionInterface::IceConnectionState new_state) {
159 RTCIceConnectionState state =
160 [[RTCPeerConnection class] iceConnectionStateForNativeState:new_state];
161 RTCPeerConnection *peer_connection = peer_connection_;
162 [peer_connection.delegate peerConnection:peer_connection
163 didChangeIceConnectionState:state];
164}
165
166void PeerConnectionDelegateAdapter::OnIceGatheringChange(
167 PeerConnectionInterface::IceGatheringState new_state) {
168 RTCIceGatheringState state =
169 [[RTCPeerConnection class] iceGatheringStateForNativeState:new_state];
170 RTCPeerConnection *peer_connection = peer_connection_;
171 [peer_connection.delegate peerConnection:peer_connection
172 didChangeIceGatheringState:state];
173}
174
175void PeerConnectionDelegateAdapter::OnIceCandidate(
176 const IceCandidateInterface *candidate) {
177 RTCIceCandidate *iceCandidate =
178 [[RTCIceCandidate alloc] initWithNativeCandidate:candidate];
179 RTCPeerConnection *peer_connection = peer_connection_;
180 [peer_connection.delegate peerConnection:peer_connection
181 didGenerateIceCandidate:iceCandidate];
182}
183} // namespace webrtc
184
185
186@implementation RTCPeerConnection {
187 NSMutableArray *_localStreams;
188 rtc::scoped_ptr<webrtc::PeerConnectionDelegateAdapter> _observer;
189 rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
190}
191
192@synthesize delegate = _delegate;
193
194- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
195 configuration:(RTCConfiguration *)configuration
196 constraints:(RTCMediaConstraints *)constraints
197 delegate:(id<RTCPeerConnectionDelegate>)delegate {
198 NSParameterAssert(factory);
199 if (self = [super init]) {
200 _observer.reset(new webrtc::PeerConnectionDelegateAdapter(self));
201 webrtc::PeerConnectionInterface::RTCConfiguration config =
202 configuration.nativeConfiguration;
hjona2f77982016-03-04 07:09:09 -0800203 rtc::scoped_ptr<webrtc::MediaConstraints> nativeConstraints =
204 constraints.nativeConstraints;
hjonf396f602016-02-11 16:19:06 -0800205 _peerConnection =
206 factory.nativeFactory->CreatePeerConnection(config,
hjona2f77982016-03-04 07:09:09 -0800207 nativeConstraints.get(),
hjonf396f602016-02-11 16:19:06 -0800208 nullptr,
209 nullptr,
210 _observer.get());
211 _localStreams = [[NSMutableArray alloc] init];
212 _delegate = delegate;
213 }
214 return self;
215}
216
217- (NSArray *)localStreams {
218 return [_localStreams copy];
219}
220
221- (RTCSessionDescription *)localDescription {
222 const webrtc::SessionDescriptionInterface *description =
223 _peerConnection->local_description();
224 return description ?
225 [[RTCSessionDescription alloc] initWithNativeDescription:description]
226 : nil;
227}
228
229- (RTCSessionDescription *)remoteDescription {
230 const webrtc::SessionDescriptionInterface *description =
231 _peerConnection->remote_description();
232 return description ?
233 [[RTCSessionDescription alloc] initWithNativeDescription:description]
234 : nil;
235}
236
237- (RTCSignalingState)signalingState {
238 return [[self class]
239 signalingStateForNativeState:_peerConnection->signaling_state()];
240}
241
242- (RTCIceConnectionState)iceConnectionState {
243 return [[self class] iceConnectionStateForNativeState:
244 _peerConnection->ice_connection_state()];
245}
246
247- (RTCIceGatheringState)iceGatheringState {
248 return [[self class] iceGatheringStateForNativeState:
249 _peerConnection->ice_gathering_state()];
250}
251
tkchinaac3eb22016-03-09 21:49:40 -0800252- (BOOL)setConfiguration:(RTCConfiguration *)configuration {
253 return _peerConnection->SetConfiguration(configuration.nativeConfiguration);
254}
255
hjonf396f602016-02-11 16:19:06 -0800256- (void)close {
257 _peerConnection->Close();
258}
259
260- (void)addIceCandidate:(RTCIceCandidate *)candidate {
261 rtc::scoped_ptr<const webrtc::IceCandidateInterface> iceCandidate(
262 candidate.nativeCandidate);
263 _peerConnection->AddIceCandidate(iceCandidate.get());
264}
265
266- (void)addStream:(RTCMediaStream *)stream {
hjona2f77982016-03-04 07:09:09 -0800267 if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
hjonf396f602016-02-11 16:19:06 -0800268 RTCLogError(@"Failed to add stream: %@", stream);
269 return;
270 }
271 [_localStreams addObject:stream];
272}
273
274- (void)removeStream:(RTCMediaStream *)stream {
275 _peerConnection->RemoveStream(stream.nativeMediaStream);
276 [_localStreams removeObject:stream];
277}
278
279- (void)offerForConstraints:(RTCMediaConstraints *)constraints
280 completionHandler:
281 (void (^)(RTCSessionDescription *sessionDescription,
282 NSError *error))completionHandler {
283 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
284 observer(new rtc::RefCountedObject
285 <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
286 _peerConnection->CreateOffer(observer, constraints.nativeConstraints.get());
287}
288
289- (void)answerForConstraints:(RTCMediaConstraints *)constraints
290 completionHandler:
291 (void (^)(RTCSessionDescription *sessionDescription,
292 NSError *error))completionHandler {
293 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
294 observer(new rtc::RefCountedObject
295 <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
296 _peerConnection->CreateAnswer(observer, constraints.nativeConstraints.get());
297}
298
299- (void)setLocalDescription:(RTCSessionDescription *)sdp
300 completionHandler:(void (^)(NSError *error))completionHandler {
301 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
302 new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
303 completionHandler));
304 _peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
305}
306
307- (void)setRemoteDescription:(RTCSessionDescription *)sdp
308 completionHandler:(void (^)(NSError *error))completionHandler {
309 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
310 new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
311 completionHandler));
312 _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription);
313}
314
skvlad79b4b872016-04-08 17:28:55 -0700315- (NSArray<RTCRtpSender *> *)senders {
316 std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenders(
317 _peerConnection->GetSenders());
318 NSMutableArray *senders = [[NSMutableArray alloc] init];
319 for (const auto &nativeSender : nativeSenders) {
320 RTCRtpSender *sender =
321 [[RTCRtpSender alloc] initWithNativeRtpSender:nativeSender];
322 [senders addObject:sender];
323 }
324 return senders;
325}
326
hjonf396f602016-02-11 16:19:06 -0800327#pragma mark - Private
328
329+ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState:
330 (RTCSignalingState)state {
331 switch (state) {
332 case RTCSignalingStateStable:
333 return webrtc::PeerConnectionInterface::kStable;
334 case RTCSignalingStateHaveLocalOffer:
335 return webrtc::PeerConnectionInterface::kHaveLocalOffer;
336 case RTCSignalingStateHaveLocalPrAnswer:
337 return webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
338 case RTCSignalingStateHaveRemoteOffer:
339 return webrtc::PeerConnectionInterface::kHaveRemoteOffer;
340 case RTCSignalingStateHaveRemotePrAnswer:
341 return webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
342 case RTCSignalingStateClosed:
343 return webrtc::PeerConnectionInterface::kClosed;
344 }
345}
346
347+ (RTCSignalingState)signalingStateForNativeState:
348 (webrtc::PeerConnectionInterface::SignalingState)nativeState {
349 switch (nativeState) {
350 case webrtc::PeerConnectionInterface::kStable:
351 return RTCSignalingStateStable;
352 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
353 return RTCSignalingStateHaveLocalOffer;
354 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
355 return RTCSignalingStateHaveLocalPrAnswer;
356 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
357 return RTCSignalingStateHaveRemoteOffer;
358 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
359 return RTCSignalingStateHaveRemotePrAnswer;
360 case webrtc::PeerConnectionInterface::kClosed:
361 return RTCSignalingStateClosed;
362 }
363}
364
365+ (NSString *)stringForSignalingState:(RTCSignalingState)state {
366 switch (state) {
367 case RTCSignalingStateStable:
368 return @"STABLE";
369 case RTCSignalingStateHaveLocalOffer:
370 return @"HAVE_LOCAL_OFFER";
371 case RTCSignalingStateHaveLocalPrAnswer:
372 return @"HAVE_LOCAL_PRANSWER";
373 case RTCSignalingStateHaveRemoteOffer:
374 return @"HAVE_REMOTE_OFFER";
375 case RTCSignalingStateHaveRemotePrAnswer:
376 return @"HAVE_REMOTE_PRANSWER";
377 case RTCSignalingStateClosed:
378 return @"CLOSED";
379 }
380}
381
382+ (webrtc::PeerConnectionInterface::IceConnectionState)
383 nativeIceConnectionStateForState:(RTCIceConnectionState)state {
384 switch (state) {
385 case RTCIceConnectionStateNew:
386 return webrtc::PeerConnectionInterface::kIceConnectionNew;
387 case RTCIceConnectionStateChecking:
388 return webrtc::PeerConnectionInterface::kIceConnectionChecking;
389 case RTCIceConnectionStateConnected:
390 return webrtc::PeerConnectionInterface::kIceConnectionConnected;
391 case RTCIceConnectionStateCompleted:
392 return webrtc::PeerConnectionInterface::kIceConnectionCompleted;
393 case RTCIceConnectionStateFailed:
394 return webrtc::PeerConnectionInterface::kIceConnectionFailed;
395 case RTCIceConnectionStateDisconnected:
396 return webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
397 case RTCIceConnectionStateClosed:
398 return webrtc::PeerConnectionInterface::kIceConnectionClosed;
hjon8bbbf2c2016-03-14 13:15:44 -0700399 case RTCIceConnectionStateCount:
hjonf396f602016-02-11 16:19:06 -0800400 return webrtc::PeerConnectionInterface::kIceConnectionMax;
401 }
402}
403
404+ (RTCIceConnectionState)iceConnectionStateForNativeState:
405 (webrtc::PeerConnectionInterface::IceConnectionState)nativeState {
406 switch (nativeState) {
407 case webrtc::PeerConnectionInterface::kIceConnectionNew:
408 return RTCIceConnectionStateNew;
409 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
410 return RTCIceConnectionStateChecking;
411 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
412 return RTCIceConnectionStateConnected;
413 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
414 return RTCIceConnectionStateCompleted;
415 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
416 return RTCIceConnectionStateFailed;
417 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
418 return RTCIceConnectionStateDisconnected;
419 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
420 return RTCIceConnectionStateClosed;
421 case webrtc::PeerConnectionInterface::kIceConnectionMax:
hjon8bbbf2c2016-03-14 13:15:44 -0700422 return RTCIceConnectionStateCount;
hjonf396f602016-02-11 16:19:06 -0800423 }
424}
425
426+ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state {
427 switch (state) {
428 case RTCIceConnectionStateNew:
429 return @"NEW";
430 case RTCIceConnectionStateChecking:
431 return @"CHECKING";
432 case RTCIceConnectionStateConnected:
433 return @"CONNECTED";
434 case RTCIceConnectionStateCompleted:
435 return @"COMPLETED";
436 case RTCIceConnectionStateFailed:
437 return @"FAILED";
438 case RTCIceConnectionStateDisconnected:
439 return @"DISCONNECTED";
440 case RTCIceConnectionStateClosed:
441 return @"CLOSED";
hjon8bbbf2c2016-03-14 13:15:44 -0700442 case RTCIceConnectionStateCount:
443 return @"COUNT";
hjonf396f602016-02-11 16:19:06 -0800444 }
445}
446
447+ (webrtc::PeerConnectionInterface::IceGatheringState)
448 nativeIceGatheringStateForState:(RTCIceGatheringState)state {
449 switch (state) {
450 case RTCIceGatheringStateNew:
451 return webrtc::PeerConnectionInterface::kIceGatheringNew;
452 case RTCIceGatheringStateGathering:
453 return webrtc::PeerConnectionInterface::kIceGatheringGathering;
454 case RTCIceGatheringStateComplete:
455 return webrtc::PeerConnectionInterface::kIceGatheringComplete;
456 }
457}
458
459+ (RTCIceGatheringState)iceGatheringStateForNativeState:
460 (webrtc::PeerConnectionInterface::IceGatheringState)nativeState {
461 switch (nativeState) {
462 case webrtc::PeerConnectionInterface::kIceGatheringNew:
463 return RTCIceGatheringStateNew;
464 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
465 return RTCIceGatheringStateGathering;
466 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
467 return RTCIceGatheringStateComplete;
468 }
469}
470
471+ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state {
472 switch (state) {
473 case RTCIceGatheringStateNew:
474 return @"NEW";
475 case RTCIceGatheringStateGathering:
476 return @"GATHERING";
477 case RTCIceGatheringStateComplete:
478 return @"COMPLETE";
479 }
480}
481
482+ (webrtc::PeerConnectionInterface::StatsOutputLevel)
483 nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level {
484 switch (level) {
485 case RTCStatsOutputLevelStandard:
486 return webrtc::PeerConnectionInterface::kStatsOutputLevelStandard;
487 case RTCStatsOutputLevelDebug:
488 return webrtc::PeerConnectionInterface::kStatsOutputLevelDebug;
489 }
490}
491
492- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)nativePeerConnection {
493 return _peerConnection;
494}
495
496@end