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