blob: 738fb313f4834ddc506aabd4d9e4d0a5f5075645 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2013, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#if !defined(__has_feature) || !__has_feature(objc_arc)
29#error "This file requires ARC support."
30#endif
31
fischman@webrtc.orgc693a2a2014-03-24 18:56:37 +000032#import "RTCPeerConnection+Internal.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000033
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000034#import "RTCDataChannel+Internal.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035#import "RTCEnumConverter.h"
fischman@webrtc.orgc693a2a2014-03-24 18:56:37 +000036#import "RTCICECandidate+Internal.h"
37#import "RTCICEServer+Internal.h"
38#import "RTCMediaConstraints+Internal.h"
39#import "RTCMediaStream+Internal.h"
tkchin@webrtc.org19b1be12014-04-22 21:05:38 +000040#import "RTCMediaStreamTrack+Internal.h"
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000041#import "RTCPeerConnectionObserver.h"
fischman@webrtc.orgc693a2a2014-03-24 18:56:37 +000042#import "RTCSessionDescription+Internal.h"
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +000043#import "RTCSessionDescriptionDelegate.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044#import "RTCSessionDescription.h"
tkchin@webrtc.org19b1be12014-04-22 21:05:38 +000045#import "RTCStatsDelegate.h"
46#import "RTCStatsReport+Internal.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047
48#include "talk/app/webrtc/jsep.h"
49
50NSString* const kRTCSessionDescriptionDelegateErrorDomain = @"RTCSDPError";
51int const kRTCSessionDescriptionDelegateErrorCode = -1;
52
53namespace webrtc {
54
55class RTCCreateSessionDescriptionObserver
56 : public CreateSessionDescriptionObserver {
57 public:
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +000058 RTCCreateSessionDescriptionObserver(
59 id<RTCSessionDescriptionDelegate> delegate,
60 RTCPeerConnection* peerConnection) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 _delegate = delegate;
62 _peerConnection = peerConnection;
63 }
64
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000065 virtual void OnSuccess(SessionDescriptionInterface* desc) OVERRIDE {
66 RTCSessionDescription* session =
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 [[RTCSessionDescription alloc] initWithSessionDescription:desc];
68 [_delegate peerConnection:_peerConnection
69 didCreateSessionDescription:session
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000070 error:nil];
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071 }
72
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000073 virtual void OnFailure(const std::string& error) OVERRIDE {
74 NSString* str = @(error.c_str());
75 NSError* err =
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain
77 code:kRTCSessionDescriptionDelegateErrorCode
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000078 userInfo:@{@"error" : str}];
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079 [_delegate peerConnection:_peerConnection
80 didCreateSessionDescription:nil
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000081 error:err];
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082 }
83
84 private:
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +000085 id<RTCSessionDescriptionDelegate> _delegate;
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000086 RTCPeerConnection* _peerConnection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087};
88
89class RTCSetSessionDescriptionObserver : public SetSessionDescriptionObserver {
90 public:
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +000091 RTCSetSessionDescriptionObserver(id<RTCSessionDescriptionDelegate> delegate,
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000092 RTCPeerConnection* peerConnection) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093 _delegate = delegate;
94 _peerConnection = peerConnection;
95 }
96
97 virtual void OnSuccess() OVERRIDE {
98 [_delegate peerConnection:_peerConnection
99 didSetSessionDescriptionWithError:nil];
100 }
101
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000102 virtual void OnFailure(const std::string& error) OVERRIDE {
103 NSString* str = @(error.c_str());
104 NSError* err =
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain
106 code:kRTCSessionDescriptionDelegateErrorCode
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000107 userInfo:@{@"error" : str}];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108 [_delegate peerConnection:_peerConnection
109 didSetSessionDescriptionWithError:err];
110 }
111
112 private:
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +0000113 id<RTCSessionDescriptionDelegate> _delegate;
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000114 RTCPeerConnection* _peerConnection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115};
tkchin@webrtc.org19b1be12014-04-22 21:05:38 +0000116
117class RTCStatsObserver : public StatsObserver {
118 public:
119 RTCStatsObserver(id<RTCStatsDelegate> delegate,
120 RTCPeerConnection* peerConnection) {
121 _delegate = delegate;
122 _peerConnection = peerConnection;
123 }
124
125 virtual void OnComplete(const std::vector<StatsReport>& reports) OVERRIDE {
126 NSMutableArray* stats = [NSMutableArray arrayWithCapacity:reports.size()];
127 std::vector<StatsReport>::const_iterator it = reports.begin();
128 for (; it != reports.end(); ++it) {
129 RTCStatsReport* statsReport =
130 [[RTCStatsReport alloc] initWithStatsReport:*it];
131 [stats addObject:statsReport];
132 }
133 [_delegate peerConnection:_peerConnection didGetStats:stats];
134 }
135
136 private:
137 id<RTCStatsDelegate> _delegate;
138 RTCPeerConnection* _peerConnection;
139};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000140}
141
142@implementation RTCPeerConnection {
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000143 NSMutableArray* _localStreams;
144 talk_base::scoped_ptr<webrtc::RTCPeerConnectionObserver> _observer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145 talk_base::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
146}
147
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000148- (BOOL)addICECandidate:(RTCICECandidate*)candidate {
fischman@webrtc.orge0034552013-12-02 18:49:54 +0000149 talk_base::scoped_ptr<const webrtc::IceCandidateInterface> iceCandidate(
150 candidate.candidate);
151 return self.peerConnection->AddIceCandidate(iceCandidate.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152}
153
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000154- (BOOL)addStream:(RTCMediaStream*)stream
155 constraints:(RTCMediaConstraints*)constraints {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156 BOOL ret = self.peerConnection->AddStream(stream.mediaStream,
157 constraints.constraints);
158 if (!ret) {
159 return NO;
160 }
161 [_localStreams addObject:stream];
162 return YES;
163}
164
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000165- (RTCDataChannel*)createDataChannelWithLabel:(NSString*)label
166 config:(RTCDataChannelInit*)config {
167 std::string labelString([label UTF8String]);
168 talk_base::scoped_refptr<webrtc::DataChannelInterface> dataChannel =
169 self.peerConnection->CreateDataChannel(labelString,
170 config.dataChannelInit);
171 return [[RTCDataChannel alloc] initWithDataChannel:dataChannel];
172}
173
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +0000174- (void)createAnswerWithDelegate:(id<RTCSessionDescriptionDelegate>)delegate
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000175 constraints:(RTCMediaConstraints*)constraints {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000176 talk_base::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver>
177 observer(new talk_base::RefCountedObject<
178 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self));
179 self.peerConnection->CreateAnswer(observer, constraints.constraints);
180}
181
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +0000182- (void)createOfferWithDelegate:(id<RTCSessionDescriptionDelegate>)delegate
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000183 constraints:(RTCMediaConstraints*)constraints {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000184 talk_base::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver>
185 observer(new talk_base::RefCountedObject<
186 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self));
187 self.peerConnection->CreateOffer(observer, constraints.constraints);
188}
189
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000190- (void)removeStream:(RTCMediaStream*)stream {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000191 self.peerConnection->RemoveStream(stream.mediaStream);
192 [_localStreams removeObject:stream];
193}
194
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000195- (void)setLocalDescriptionWithDelegate:
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +0000196 (id<RTCSessionDescriptionDelegate>)delegate
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000197 sessionDescription:(RTCSessionDescription*)sdp {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000198 talk_base::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer(
199 new talk_base::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>(
200 delegate, self));
201 self.peerConnection->SetLocalDescription(observer, sdp.sessionDescription);
202}
203
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000204- (void)setRemoteDescriptionWithDelegate:
tkchin@webrtc.orgec3d8ec2014-04-21 18:47:24 +0000205 (id<RTCSessionDescriptionDelegate>)delegate
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000206 sessionDescription:(RTCSessionDescription*)sdp {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 talk_base::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer(
208 new talk_base::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>(
209 delegate, self));
210 self.peerConnection->SetRemoteDescription(observer, sdp.sessionDescription);
211}
212
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000213- (BOOL)updateICEServers:(NSArray*)servers
214 constraints:(RTCMediaConstraints*)constraints {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 webrtc::PeerConnectionInterface::IceServers iceServers;
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000216 for (RTCICEServer* server in servers) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000217 iceServers.push_back(server.iceServer);
218 }
219 return self.peerConnection->UpdateIce(iceServers, constraints.constraints);
220}
221
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000222- (RTCSessionDescription*)localDescription {
223 const webrtc::SessionDescriptionInterface* sdi =
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224 self.peerConnection->local_description();
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000225 return sdi ? [[RTCSessionDescription alloc] initWithSessionDescription:sdi]
226 : nil;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227}
228
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000229- (NSArray*)localStreams {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230 return [_localStreams copy];
231}
232
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000233- (RTCSessionDescription*)remoteDescription {
234 const webrtc::SessionDescriptionInterface* sdi =
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000235 self.peerConnection->remote_description();
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000236 return sdi ? [[RTCSessionDescription alloc] initWithSessionDescription:sdi]
237 : nil;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238}
239
240- (RTCICEConnectionState)iceConnectionState {
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000241 return [RTCEnumConverter
242 convertIceConnectionStateToObjC:self.peerConnection
243 ->ice_connection_state()];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244}
245
246- (RTCICEGatheringState)iceGatheringState {
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000247 return [RTCEnumConverter
248 convertIceGatheringStateToObjC:self.peerConnection
249 ->ice_gathering_state()];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000250}
251
252- (RTCSignalingState)signalingState {
253 return [RTCEnumConverter
254 convertSignalingStateToObjC:self.peerConnection->signaling_state()];
255}
256
257- (void)close {
258 self.peerConnection->Close();
259}
260
tkchin@webrtc.org19b1be12014-04-22 21:05:38 +0000261- (BOOL)getStatsWithDelegate:(id<RTCStatsDelegate>)delegate
262 mediaStreamTrack:(RTCMediaStreamTrack*)mediaStreamTrack
263 statsOutputLevel:(RTCStatsOutputLevel)statsOutputLevel {
264 talk_base::scoped_refptr<webrtc::RTCStatsObserver> observer(
265 new talk_base::RefCountedObject<webrtc::RTCStatsObserver>(delegate,
266 self));
267 webrtc::PeerConnectionInterface::StatsOutputLevel nativeOutputLevel =
268 [RTCEnumConverter convertStatsOutputLevelToNative:statsOutputLevel];
269 return self.peerConnection->GetStats(
270 observer, mediaStreamTrack.mediaTrack, nativeOutputLevel);
271}
272
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000273@end
274
275@implementation RTCPeerConnection (Internal)
276
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000277- (instancetype)initWithFactory:(webrtc::PeerConnectionFactoryInterface*)factory
278 iceServers:(const webrtc::PeerConnectionInterface::IceServers&)iceServers
279 constraints:(const webrtc::MediaConstraintsInterface*)constraints {
280 NSParameterAssert(factory != NULL);
281 if (self = [super init]) {
282 _observer.reset(new webrtc::RTCPeerConnectionObserver(self));
283 _peerConnection = factory->CreatePeerConnection(
284 iceServers, constraints, NULL, NULL, _observer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 _localStreams = [[NSMutableArray alloc] init];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 }
287 return self;
288}
289
290- (talk_base::scoped_refptr<webrtc::PeerConnectionInterface>)peerConnection {
291 return _peerConnection;
292}
293
294@end