blob: 73dce36f0aa7efde1c46a2791c07cb4afcb1c055 [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
32#import "RTCPeerConnection+internal.h"
33
34#import "RTCEnumConverter.h"
35#import "RTCICECandidate+internal.h"
36#import "RTCICEServer+internal.h"
37#import "RTCMediaConstraints+internal.h"
38#import "RTCMediaStream+internal.h"
39#import "RTCSessionDescription+internal.h"
40#import "RTCSessionDescriptonDelegate.h"
41#import "RTCSessionDescription.h"
42
43#include "talk/app/webrtc/jsep.h"
44
45NSString* const kRTCSessionDescriptionDelegateErrorDomain = @"RTCSDPError";
46int const kRTCSessionDescriptionDelegateErrorCode = -1;
47
48namespace webrtc {
49
50class RTCCreateSessionDescriptionObserver
51 : public CreateSessionDescriptionObserver {
52 public:
53 RTCCreateSessionDescriptionObserver(id<RTCSessionDescriptonDelegate> delegate,
54 RTCPeerConnection *peerConnection) {
55 _delegate = delegate;
56 _peerConnection = peerConnection;
57 }
58
59 virtual void OnSuccess(SessionDescriptionInterface *desc) OVERRIDE {
60 RTCSessionDescription *session =
61 [[RTCSessionDescription alloc] initWithSessionDescription:desc];
62 [_delegate peerConnection:_peerConnection
63 didCreateSessionDescription:session
64 error:nil];
65 }
66
67 virtual void OnFailure(const std::string &error) OVERRIDE {
68 NSString *str = @(error.c_str());
69 NSError *err =
70 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain
71 code:kRTCSessionDescriptionDelegateErrorCode
72 userInfo:@{ @"error" : str }];
73 [_delegate peerConnection:_peerConnection
74 didCreateSessionDescription:nil
75 error:err];
76 }
77
78 private:
79 id<RTCSessionDescriptonDelegate> _delegate;
80 RTCPeerConnection *_peerConnection;
81};
82
83class RTCSetSessionDescriptionObserver : public SetSessionDescriptionObserver {
84 public:
85 RTCSetSessionDescriptionObserver(id<RTCSessionDescriptonDelegate> delegate,
86 RTCPeerConnection *peerConnection) {
87 _delegate = delegate;
88 _peerConnection = peerConnection;
89 }
90
91 virtual void OnSuccess() OVERRIDE {
92 [_delegate peerConnection:_peerConnection
93 didSetSessionDescriptionWithError:nil];
94 }
95
96 virtual void OnFailure(const std::string &error) OVERRIDE {
97 NSString *str = @(error.c_str());
98 NSError *err =
99 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain
100 code:kRTCSessionDescriptionDelegateErrorCode
101 userInfo:@{ @"error" : str }];
102 [_delegate peerConnection:_peerConnection
103 didSetSessionDescriptionWithError:err];
104 }
105
106 private:
107 id<RTCSessionDescriptonDelegate> _delegate;
108 RTCPeerConnection *_peerConnection;
109};
110
111}
112
113@implementation RTCPeerConnection {
114 NSMutableArray *_localStreams;
115 talk_base::scoped_ptr<webrtc::RTCPeerConnectionObserver>_observer;
116 talk_base::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
117}
118
119- (BOOL)addICECandidate:(RTCICECandidate *)candidate {
120 const webrtc::IceCandidateInterface *iceCandidate = candidate.candidate;
121 return self.peerConnection->AddIceCandidate(iceCandidate);
122 delete iceCandidate;
123}
124
125- (BOOL)addStream:(RTCMediaStream *)stream
126 constraints:(RTCMediaConstraints *)constraints {
127 BOOL ret = self.peerConnection->AddStream(stream.mediaStream,
128 constraints.constraints);
129 if (!ret) {
130 return NO;
131 }
132 [_localStreams addObject:stream];
133 return YES;
134}
135
136- (void)createAnswerWithDelegate:(id<RTCSessionDescriptonDelegate>)delegate
137 constraints:(RTCMediaConstraints *)constraints {
138 talk_base::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver>
139 observer(new talk_base::RefCountedObject<
140 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self));
141 self.peerConnection->CreateAnswer(observer, constraints.constraints);
142}
143
144- (void)createOfferWithDelegate:(id<RTCSessionDescriptonDelegate>)delegate
145 constraints:(RTCMediaConstraints *)constraints {
146 talk_base::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver>
147 observer(new talk_base::RefCountedObject<
148 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self));
149 self.peerConnection->CreateOffer(observer, constraints.constraints);
150}
151
152- (void)removeStream:(RTCMediaStream *)stream {
153 self.peerConnection->RemoveStream(stream.mediaStream);
154 [_localStreams removeObject:stream];
155}
156
157- (void)
158 setLocalDescriptionWithDelegate:(id<RTCSessionDescriptonDelegate>)delegate
159 sessionDescription:(RTCSessionDescription *)sdp {
160 talk_base::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer(
161 new talk_base::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>(
162 delegate, self));
163 self.peerConnection->SetLocalDescription(observer, sdp.sessionDescription);
164}
165
166- (void)
167 setRemoteDescriptionWithDelegate:(id<RTCSessionDescriptonDelegate>)delegate
168 sessionDescription:(RTCSessionDescription *)sdp {
169 talk_base::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer(
170 new talk_base::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>(
171 delegate, self));
172 self.peerConnection->SetRemoteDescription(observer, sdp.sessionDescription);
173}
174
175- (BOOL)updateICEServers:(NSArray *)servers
176 constraints:(RTCMediaConstraints *)constraints {
177 webrtc::PeerConnectionInterface::IceServers iceServers;
178 for (RTCICEServer *server in servers) {
179 iceServers.push_back(server.iceServer);
180 }
181 return self.peerConnection->UpdateIce(iceServers, constraints.constraints);
182}
183
184- (RTCSessionDescription *)localDescription {
185 const webrtc::SessionDescriptionInterface *sdi =
186 self.peerConnection->local_description();
187 return sdi ?
188 [[RTCSessionDescription alloc] initWithSessionDescription:sdi] :
189 nil;
190}
191
192- (NSArray *)localStreams {
193 return [_localStreams copy];
194}
195
196- (RTCSessionDescription *)remoteDescription {
197 const webrtc::SessionDescriptionInterface *sdi =
198 self.peerConnection->remote_description();
199 return sdi ?
200 [[RTCSessionDescription alloc] initWithSessionDescription:sdi] :
201 nil;
202}
203
204- (RTCICEConnectionState)iceConnectionState {
205 return [RTCEnumConverter convertIceConnectionStateToObjC:
206 self.peerConnection->ice_connection_state()];
207}
208
209- (RTCICEGatheringState)iceGatheringState {
210 return [RTCEnumConverter convertIceGatheringStateToObjC:
211 self.peerConnection->ice_gathering_state()];
212}
213
214- (RTCSignalingState)signalingState {
215 return [RTCEnumConverter
216 convertSignalingStateToObjC:self.peerConnection->signaling_state()];
217}
218
219- (void)close {
220 self.peerConnection->Close();
221}
222
223@end
224
225@implementation RTCPeerConnection (Internal)
226
227- (id)initWithPeerConnection:(
228 talk_base::scoped_refptr<webrtc::PeerConnectionInterface>)peerConnection
229 observer:(webrtc::RTCPeerConnectionObserver *)observer {
230 if (!peerConnection || !observer) {
231 NSAssert(NO, @"nil arguments not allowed");
232 self = nil;
233 return nil;
234 }
235 if ((self = [super init])) {
236 _peerConnection = peerConnection;
237 _localStreams = [[NSMutableArray alloc] init];
238 _observer.reset(observer);
239 }
240 return self;
241}
242
243- (talk_base::scoped_refptr<webrtc::PeerConnectionInterface>)peerConnection {
244 return _peerConnection;
245}
246
247@end