1 /* 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 "RTCDataChannel+Internal.h" 35 #import "RTCEnumConverter.h" 36 #import "RTCICECandidate+Internal.h" 37 #import "RTCICEServer+Internal.h" 38 #import "RTCMediaConstraints+Internal.h" 39 #import "RTCMediaStream+Internal.h" 40 #import "RTCMediaStreamTrack+Internal.h" 41 #import "RTCPeerConnectionObserver.h" 42 #import "RTCSessionDescription+Internal.h" 43 #import "RTCSessionDescription.h" 44 #import "RTCSessionDescriptionDelegate.h" 45 #import "RTCStatsDelegate.h" 46 #import "RTCStatsReport+Internal.h" 47 48 #include "talk/app/webrtc/jsep.h" 49 50 NSString* const kRTCSessionDescriptionDelegateErrorDomain = @"RTCSDPError"; 51 int const kRTCSessionDescriptionDelegateErrorCode = -1; 52 53 namespace webrtc { 54 55 class RTCCreateSessionDescriptionObserver 56 : public CreateSessionDescriptionObserver { 57 public: 58 RTCCreateSessionDescriptionObserver( 59 id<RTCSessionDescriptionDelegate> delegate, 60 RTCPeerConnection* peerConnection) { 61 _delegate = delegate; 62 _peerConnection = peerConnection; 63 } 64 65 virtual void OnSuccess(SessionDescriptionInterface* desc) OVERRIDE { 66 RTCSessionDescription* session = 67 [[RTCSessionDescription alloc] initWithSessionDescription:desc]; 68 [_delegate peerConnection:_peerConnection 69 didCreateSessionDescription:session 70 error:nil]; 71 } 72 73 virtual void OnFailure(const std::string& error) OVERRIDE { 74 NSString* str = @(error.c_str()); 75 NSError* err = 76 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain 77 code:kRTCSessionDescriptionDelegateErrorCode 78 userInfo:@{@"error" : str}]; 79 [_delegate peerConnection:_peerConnection 80 didCreateSessionDescription:nil 81 error:err]; 82 } 83 84 private: 85 id<RTCSessionDescriptionDelegate> _delegate; 86 RTCPeerConnection* _peerConnection; 87 }; 88 89 class RTCSetSessionDescriptionObserver : public SetSessionDescriptionObserver { 90 public: 91 RTCSetSessionDescriptionObserver(id<RTCSessionDescriptionDelegate> delegate, 92 RTCPeerConnection* peerConnection) { 93 _delegate = delegate; 94 _peerConnection = peerConnection; 95 } 96 97 virtual void OnSuccess() OVERRIDE { 98 [_delegate peerConnection:_peerConnection 99 didSetSessionDescriptionWithError:nil]; 100 } 101 102 virtual void OnFailure(const std::string& error) OVERRIDE { 103 NSString* str = @(error.c_str()); 104 NSError* err = 105 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain 106 code:kRTCSessionDescriptionDelegateErrorCode 107 userInfo:@{@"error" : str}]; 108 [_delegate peerConnection:_peerConnection 109 didSetSessionDescriptionWithError:err]; 110 } 111 112 private: 113 id<RTCSessionDescriptionDelegate> _delegate; 114 RTCPeerConnection* _peerConnection; 115 }; 116 117 class 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 }; 140 } 141 142 @implementation RTCPeerConnection { 143 NSMutableArray* _localStreams; 144 rtc::scoped_ptr<webrtc::RTCPeerConnectionObserver> _observer; 145 rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection; 146 } 147 148 - (BOOL)addICECandidate:(RTCICECandidate*)candidate { 149 rtc::scoped_ptr<const webrtc::IceCandidateInterface> iceCandidate( 150 candidate.candidate); 151 return self.peerConnection->AddIceCandidate(iceCandidate.get()); 152 } 153 154 - (BOOL)addStream:(RTCMediaStream*)stream 155 constraints:(RTCMediaConstraints*)constraints { 156 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 165 - (RTCDataChannel*)createDataChannelWithLabel:(NSString*)label 166 config:(RTCDataChannelInit*)config { 167 std::string labelString([label UTF8String]); 168 rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel = 169 self.peerConnection->CreateDataChannel(labelString, 170 config.dataChannelInit); 171 return [[RTCDataChannel alloc] initWithDataChannel:dataChannel]; 172 } 173 174 - (void)createAnswerWithDelegate:(id<RTCSessionDescriptionDelegate>)delegate 175 constraints:(RTCMediaConstraints*)constraints { 176 rtc::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver> 177 observer(new rtc::RefCountedObject< 178 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self)); 179 self.peerConnection->CreateAnswer(observer, constraints.constraints); 180 } 181 182 - (void)createOfferWithDelegate:(id<RTCSessionDescriptionDelegate>)delegate 183 constraints:(RTCMediaConstraints*)constraints { 184 rtc::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver> 185 observer(new rtc::RefCountedObject< 186 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self)); 187 self.peerConnection->CreateOffer(observer, constraints.constraints); 188 } 189 190 - (void)removeStream:(RTCMediaStream*)stream { 191 self.peerConnection->RemoveStream(stream.mediaStream); 192 [_localStreams removeObject:stream]; 193 } 194 195 - (void)setLocalDescriptionWithDelegate: 196 (id<RTCSessionDescriptionDelegate>)delegate 197 sessionDescription:(RTCSessionDescription*)sdp { 198 rtc::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer( 199 new rtc::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>( 200 delegate, self)); 201 self.peerConnection->SetLocalDescription(observer, sdp.sessionDescription); 202 } 203 204 - (void)setRemoteDescriptionWithDelegate: 205 (id<RTCSessionDescriptionDelegate>)delegate 206 sessionDescription:(RTCSessionDescription*)sdp { 207 rtc::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer( 208 new rtc::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>( 209 delegate, self)); 210 self.peerConnection->SetRemoteDescription(observer, sdp.sessionDescription); 211 } 212 213 - (BOOL)updateICEServers:(NSArray*)servers 214 constraints:(RTCMediaConstraints*)constraints { 215 webrtc::PeerConnectionInterface::IceServers iceServers; 216 for (RTCICEServer* server in servers) { 217 iceServers.push_back(server.iceServer); 218 } 219 return self.peerConnection->UpdateIce(iceServers, constraints.constraints); 220 } 221 222 - (RTCSessionDescription*)localDescription { 223 const webrtc::SessionDescriptionInterface* sdi = 224 self.peerConnection->local_description(); 225 return sdi ? [[RTCSessionDescription alloc] initWithSessionDescription:sdi] 226 : nil; 227 } 228 229 - (NSArray*)localStreams { 230 return [_localStreams copy]; 231 } 232 233 - (RTCSessionDescription*)remoteDescription { 234 const webrtc::SessionDescriptionInterface* sdi = 235 self.peerConnection->remote_description(); 236 return sdi ? [[RTCSessionDescription alloc] initWithSessionDescription:sdi] 237 : nil; 238 } 239 240 - (RTCICEConnectionState)iceConnectionState { 241 return [RTCEnumConverter 242 convertIceConnectionStateToObjC:self.peerConnection 243 ->ice_connection_state()]; 244 } 245 246 - (RTCICEGatheringState)iceGatheringState { 247 return [RTCEnumConverter 248 convertIceGatheringStateToObjC:self.peerConnection 249 ->ice_gathering_state()]; 250 } 251 252 - (RTCSignalingState)signalingState { 253 return [RTCEnumConverter 254 convertSignalingStateToObjC:self.peerConnection->signaling_state()]; 255 } 256 257 - (void)close { 258 self.peerConnection->Close(); 259 } 260 261 - (BOOL)getStatsWithDelegate:(id<RTCStatsDelegate>)delegate 262 mediaStreamTrack:(RTCMediaStreamTrack*)mediaStreamTrack 263 statsOutputLevel:(RTCStatsOutputLevel)statsOutputLevel { 264 rtc::scoped_refptr<webrtc::RTCStatsObserver> observer( 265 new rtc::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 273 @end 274 275 @implementation RTCPeerConnection (Internal) 276 277 - (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()); 285 _localStreams = [[NSMutableArray alloc] init]; 286 } 287 return self; 288 } 289 290 - (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)peerConnection { 291 return _peerConnection; 292 } 293 294 @end 295