blob: f75d6636fa8b81e87d431f8bab01c022d9bc493e [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;
202 webrtc::MediaConstraints *nativeConstraints =
203 constraints.nativeConstraints.get();
204 _peerConnection =
205 factory.nativeFactory->CreatePeerConnection(config,
206 nativeConstraints,
207 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
251- (void)close {
252 _peerConnection->Close();
253}
254
255- (void)addIceCandidate:(RTCIceCandidate *)candidate {
256 rtc::scoped_ptr<const webrtc::IceCandidateInterface> iceCandidate(
257 candidate.nativeCandidate);
258 _peerConnection->AddIceCandidate(iceCandidate.get());
259}
260
261- (void)addStream:(RTCMediaStream *)stream {
262 if (_peerConnection->AddStream(stream.nativeMediaStream)) {
263 RTCLogError(@"Failed to add stream: %@", stream);
264 return;
265 }
266 [_localStreams addObject:stream];
267}
268
269- (void)removeStream:(RTCMediaStream *)stream {
270 _peerConnection->RemoveStream(stream.nativeMediaStream);
271 [_localStreams removeObject:stream];
272}
273
274- (void)offerForConstraints:(RTCMediaConstraints *)constraints
275 completionHandler:
276 (void (^)(RTCSessionDescription *sessionDescription,
277 NSError *error))completionHandler {
278 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
279 observer(new rtc::RefCountedObject
280 <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
281 _peerConnection->CreateOffer(observer, constraints.nativeConstraints.get());
282}
283
284- (void)answerForConstraints:(RTCMediaConstraints *)constraints
285 completionHandler:
286 (void (^)(RTCSessionDescription *sessionDescription,
287 NSError *error))completionHandler {
288 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
289 observer(new rtc::RefCountedObject
290 <webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
291 _peerConnection->CreateAnswer(observer, constraints.nativeConstraints.get());
292}
293
294- (void)setLocalDescription:(RTCSessionDescription *)sdp
295 completionHandler:(void (^)(NSError *error))completionHandler {
296 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
297 new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
298 completionHandler));
299 _peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
300}
301
302- (void)setRemoteDescription:(RTCSessionDescription *)sdp
303 completionHandler:(void (^)(NSError *error))completionHandler {
304 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
305 new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
306 completionHandler));
307 _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription);
308}
309
310#pragma mark - Private
311
312+ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState:
313 (RTCSignalingState)state {
314 switch (state) {
315 case RTCSignalingStateStable:
316 return webrtc::PeerConnectionInterface::kStable;
317 case RTCSignalingStateHaveLocalOffer:
318 return webrtc::PeerConnectionInterface::kHaveLocalOffer;
319 case RTCSignalingStateHaveLocalPrAnswer:
320 return webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
321 case RTCSignalingStateHaveRemoteOffer:
322 return webrtc::PeerConnectionInterface::kHaveRemoteOffer;
323 case RTCSignalingStateHaveRemotePrAnswer:
324 return webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
325 case RTCSignalingStateClosed:
326 return webrtc::PeerConnectionInterface::kClosed;
327 }
328}
329
330+ (RTCSignalingState)signalingStateForNativeState:
331 (webrtc::PeerConnectionInterface::SignalingState)nativeState {
332 switch (nativeState) {
333 case webrtc::PeerConnectionInterface::kStable:
334 return RTCSignalingStateStable;
335 case webrtc::PeerConnectionInterface::kHaveLocalOffer:
336 return RTCSignalingStateHaveLocalOffer;
337 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
338 return RTCSignalingStateHaveLocalPrAnswer;
339 case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
340 return RTCSignalingStateHaveRemoteOffer;
341 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
342 return RTCSignalingStateHaveRemotePrAnswer;
343 case webrtc::PeerConnectionInterface::kClosed:
344 return RTCSignalingStateClosed;
345 }
346}
347
348+ (NSString *)stringForSignalingState:(RTCSignalingState)state {
349 switch (state) {
350 case RTCSignalingStateStable:
351 return @"STABLE";
352 case RTCSignalingStateHaveLocalOffer:
353 return @"HAVE_LOCAL_OFFER";
354 case RTCSignalingStateHaveLocalPrAnswer:
355 return @"HAVE_LOCAL_PRANSWER";
356 case RTCSignalingStateHaveRemoteOffer:
357 return @"HAVE_REMOTE_OFFER";
358 case RTCSignalingStateHaveRemotePrAnswer:
359 return @"HAVE_REMOTE_PRANSWER";
360 case RTCSignalingStateClosed:
361 return @"CLOSED";
362 }
363}
364
365+ (webrtc::PeerConnectionInterface::IceConnectionState)
366 nativeIceConnectionStateForState:(RTCIceConnectionState)state {
367 switch (state) {
368 case RTCIceConnectionStateNew:
369 return webrtc::PeerConnectionInterface::kIceConnectionNew;
370 case RTCIceConnectionStateChecking:
371 return webrtc::PeerConnectionInterface::kIceConnectionChecking;
372 case RTCIceConnectionStateConnected:
373 return webrtc::PeerConnectionInterface::kIceConnectionConnected;
374 case RTCIceConnectionStateCompleted:
375 return webrtc::PeerConnectionInterface::kIceConnectionCompleted;
376 case RTCIceConnectionStateFailed:
377 return webrtc::PeerConnectionInterface::kIceConnectionFailed;
378 case RTCIceConnectionStateDisconnected:
379 return webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
380 case RTCIceConnectionStateClosed:
381 return webrtc::PeerConnectionInterface::kIceConnectionClosed;
382 case RTCIceConnectionStateMax:
383 return webrtc::PeerConnectionInterface::kIceConnectionMax;
384 }
385}
386
387+ (RTCIceConnectionState)iceConnectionStateForNativeState:
388 (webrtc::PeerConnectionInterface::IceConnectionState)nativeState {
389 switch (nativeState) {
390 case webrtc::PeerConnectionInterface::kIceConnectionNew:
391 return RTCIceConnectionStateNew;
392 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
393 return RTCIceConnectionStateChecking;
394 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
395 return RTCIceConnectionStateConnected;
396 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
397 return RTCIceConnectionStateCompleted;
398 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
399 return RTCIceConnectionStateFailed;
400 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
401 return RTCIceConnectionStateDisconnected;
402 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
403 return RTCIceConnectionStateClosed;
404 case webrtc::PeerConnectionInterface::kIceConnectionMax:
405 return RTCIceConnectionStateMax;
406 }
407}
408
409+ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state {
410 switch (state) {
411 case RTCIceConnectionStateNew:
412 return @"NEW";
413 case RTCIceConnectionStateChecking:
414 return @"CHECKING";
415 case RTCIceConnectionStateConnected:
416 return @"CONNECTED";
417 case RTCIceConnectionStateCompleted:
418 return @"COMPLETED";
419 case RTCIceConnectionStateFailed:
420 return @"FAILED";
421 case RTCIceConnectionStateDisconnected:
422 return @"DISCONNECTED";
423 case RTCIceConnectionStateClosed:
424 return @"CLOSED";
425 case RTCIceConnectionStateMax:
426 return @"MAX";
427 }
428}
429
430+ (webrtc::PeerConnectionInterface::IceGatheringState)
431 nativeIceGatheringStateForState:(RTCIceGatheringState)state {
432 switch (state) {
433 case RTCIceGatheringStateNew:
434 return webrtc::PeerConnectionInterface::kIceGatheringNew;
435 case RTCIceGatheringStateGathering:
436 return webrtc::PeerConnectionInterface::kIceGatheringGathering;
437 case RTCIceGatheringStateComplete:
438 return webrtc::PeerConnectionInterface::kIceGatheringComplete;
439 }
440}
441
442+ (RTCIceGatheringState)iceGatheringStateForNativeState:
443 (webrtc::PeerConnectionInterface::IceGatheringState)nativeState {
444 switch (nativeState) {
445 case webrtc::PeerConnectionInterface::kIceGatheringNew:
446 return RTCIceGatheringStateNew;
447 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
448 return RTCIceGatheringStateGathering;
449 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
450 return RTCIceGatheringStateComplete;
451 }
452}
453
454+ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state {
455 switch (state) {
456 case RTCIceGatheringStateNew:
457 return @"NEW";
458 case RTCIceGatheringStateGathering:
459 return @"GATHERING";
460 case RTCIceGatheringStateComplete:
461 return @"COMPLETE";
462 }
463}
464
465+ (webrtc::PeerConnectionInterface::StatsOutputLevel)
466 nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level {
467 switch (level) {
468 case RTCStatsOutputLevelStandard:
469 return webrtc::PeerConnectionInterface::kStatsOutputLevelStandard;
470 case RTCStatsOutputLevelDebug:
471 return webrtc::PeerConnectionInterface::kStatsOutputLevelDebug;
472 }
473}
474
475- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)nativePeerConnection {
476 return _peerConnection;
477}
478
479@end