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 50NSString* const kRTCSessionDescriptionDelegateErrorDomain = @"RTCSDPError"; 51int const kRTCSessionDescriptionDelegateErrorCode = -1; 52 53namespace webrtc { 54 55class RTCCreateSessionDescriptionObserver 56 : public CreateSessionDescriptionObserver { 57 public: 58 RTCCreateSessionDescriptionObserver( 59 id<RTCSessionDescriptionDelegate> delegate, 60 RTCPeerConnection* peerConnection) { 61 _delegate = delegate; 62 _peerConnection = peerConnection; 63 } 64 65 void OnSuccess(SessionDescriptionInterface* desc) override { 66 RTCSessionDescription* session = 67 [[RTCSessionDescription alloc] initWithSessionDescription:desc]; 68 [_delegate peerConnection:_peerConnection 69 didCreateSessionDescription:session 70 error:nil]; 71 delete desc; 72 } 73 74 void OnFailure(const std::string& error) override { 75 NSString* str = @(error.c_str()); 76 NSError* err = 77 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain 78 code:kRTCSessionDescriptionDelegateErrorCode 79 userInfo:@{@"error" : str}]; 80 [_delegate peerConnection:_peerConnection 81 didCreateSessionDescription:nil 82 error:err]; 83 } 84 85 private: 86 id<RTCSessionDescriptionDelegate> _delegate; 87 RTCPeerConnection* _peerConnection; 88}; 89 90class RTCSetSessionDescriptionObserver : public SetSessionDescriptionObserver { 91 public: 92 RTCSetSessionDescriptionObserver(id<RTCSessionDescriptionDelegate> delegate, 93 RTCPeerConnection* peerConnection) { 94 _delegate = delegate; 95 _peerConnection = peerConnection; 96 } 97 98 void OnSuccess() override { 99 [_delegate peerConnection:_peerConnection 100 didSetSessionDescriptionWithError:nil]; 101 } 102 103 void OnFailure(const std::string& error) override { 104 NSString* str = @(error.c_str()); 105 NSError* err = 106 [NSError errorWithDomain:kRTCSessionDescriptionDelegateErrorDomain 107 code:kRTCSessionDescriptionDelegateErrorCode 108 userInfo:@{@"error" : str}]; 109 [_delegate peerConnection:_peerConnection 110 didSetSessionDescriptionWithError:err]; 111 } 112 113 private: 114 id<RTCSessionDescriptionDelegate> _delegate; 115 RTCPeerConnection* _peerConnection; 116}; 117 118class RTCStatsObserver : public StatsObserver { 119 public: 120 RTCStatsObserver(id<RTCStatsDelegate> delegate, 121 RTCPeerConnection* peerConnection) { 122 _delegate = delegate; 123 _peerConnection = peerConnection; 124 } 125 126 void OnComplete(const StatsReports& reports) override { 127 NSMutableArray* stats = [NSMutableArray arrayWithCapacity:reports.size()]; 128 for (const auto* report : reports) { 129 RTCStatsReport* statsReport = 130 [[RTCStatsReport alloc] initWithStatsReport:*report]; 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 BOOL ret = self.peerConnection->AddStream(stream.mediaStream); 156 if (!ret) { 157 return NO; 158 } 159 [_localStreams addObject:stream]; 160 return YES; 161} 162 163- (RTCDataChannel*)createDataChannelWithLabel:(NSString*)label 164 config:(RTCDataChannelInit*)config { 165 std::string labelString([label UTF8String]); 166 rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel = 167 self.peerConnection->CreateDataChannel(labelString, 168 config.dataChannelInit); 169 return [[RTCDataChannel alloc] initWithDataChannel:dataChannel]; 170} 171 172- (void)createAnswerWithDelegate:(id<RTCSessionDescriptionDelegate>)delegate 173 constraints:(RTCMediaConstraints*)constraints { 174 rtc::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver> 175 observer(new rtc::RefCountedObject< 176 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self)); 177 self.peerConnection->CreateAnswer(observer, constraints.constraints); 178} 179 180- (void)createOfferWithDelegate:(id<RTCSessionDescriptionDelegate>)delegate 181 constraints:(RTCMediaConstraints*)constraints { 182 rtc::scoped_refptr<webrtc::RTCCreateSessionDescriptionObserver> 183 observer(new rtc::RefCountedObject< 184 webrtc::RTCCreateSessionDescriptionObserver>(delegate, self)); 185 self.peerConnection->CreateOffer(observer, constraints.constraints); 186} 187 188- (void)removeStream:(RTCMediaStream*)stream { 189 self.peerConnection->RemoveStream(stream.mediaStream); 190 [_localStreams removeObject:stream]; 191} 192 193- (void)setLocalDescriptionWithDelegate: 194 (id<RTCSessionDescriptionDelegate>)delegate 195 sessionDescription:(RTCSessionDescription*)sdp { 196 rtc::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer( 197 new rtc::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>( 198 delegate, self)); 199 self.peerConnection->SetLocalDescription(observer, sdp.sessionDescription); 200} 201 202- (void)setRemoteDescriptionWithDelegate: 203 (id<RTCSessionDescriptionDelegate>)delegate 204 sessionDescription:(RTCSessionDescription*)sdp { 205 rtc::scoped_refptr<webrtc::RTCSetSessionDescriptionObserver> observer( 206 new rtc::RefCountedObject<webrtc::RTCSetSessionDescriptionObserver>( 207 delegate, self)); 208 self.peerConnection->SetRemoteDescription(observer, sdp.sessionDescription); 209} 210 211- (BOOL)setConfiguration:(RTCConfiguration *)configuration { 212 return self.peerConnection->SetConfiguration( 213 configuration.nativeConfiguration); 214} 215 216- (RTCSessionDescription*)localDescription { 217 const webrtc::SessionDescriptionInterface* sdi = 218 self.peerConnection->local_description(); 219 return sdi ? [[RTCSessionDescription alloc] initWithSessionDescription:sdi] 220 : nil; 221} 222 223- (NSArray*)localStreams { 224 return [_localStreams copy]; 225} 226 227- (RTCSessionDescription*)remoteDescription { 228 const webrtc::SessionDescriptionInterface* sdi = 229 self.peerConnection->remote_description(); 230 return sdi ? [[RTCSessionDescription alloc] initWithSessionDescription:sdi] 231 : nil; 232} 233 234- (RTCICEConnectionState)iceConnectionState { 235 return [RTCEnumConverter 236 convertIceConnectionStateToObjC:self.peerConnection 237 ->ice_connection_state()]; 238} 239 240- (RTCICEGatheringState)iceGatheringState { 241 return [RTCEnumConverter 242 convertIceGatheringStateToObjC:self.peerConnection 243 ->ice_gathering_state()]; 244} 245 246- (RTCSignalingState)signalingState { 247 return [RTCEnumConverter 248 convertSignalingStateToObjC:self.peerConnection->signaling_state()]; 249} 250 251- (void)close { 252 self.peerConnection->Close(); 253} 254 255- (BOOL)getStatsWithDelegate:(id<RTCStatsDelegate>)delegate 256 mediaStreamTrack:(RTCMediaStreamTrack*)mediaStreamTrack 257 statsOutputLevel:(RTCStatsOutputLevel)statsOutputLevel { 258 rtc::scoped_refptr<webrtc::RTCStatsObserver> observer( 259 new rtc::RefCountedObject<webrtc::RTCStatsObserver>(delegate, 260 self)); 261 webrtc::PeerConnectionInterface::StatsOutputLevel nativeOutputLevel = 262 [RTCEnumConverter convertStatsOutputLevelToNative:statsOutputLevel]; 263 return self.peerConnection->GetStats( 264 observer, mediaStreamTrack.mediaTrack, nativeOutputLevel); 265} 266 267@end 268 269@implementation RTCPeerConnection (Internal) 270 271- (instancetype)initWithFactory:(webrtc::PeerConnectionFactoryInterface*)factory 272 iceServers:(const webrtc::PeerConnectionInterface::IceServers&)iceServers 273 constraints:(const webrtc::MediaConstraintsInterface*)constraints { 274 NSParameterAssert(factory != nullptr); 275 if (self = [super init]) { 276 webrtc::PeerConnectionInterface::RTCConfiguration config; 277 config.servers = iceServers; 278 _observer.reset(new webrtc::RTCPeerConnectionObserver(self)); 279 _peerConnection = factory->CreatePeerConnection( 280 config, constraints, nullptr, nullptr, _observer.get()); 281 _localStreams = [[NSMutableArray alloc] init]; 282 } 283 return self; 284} 285 286- (instancetype)initWithFactory:(webrtc::PeerConnectionFactoryInterface *)factory 287 config:(const webrtc::PeerConnectionInterface::RTCConfiguration &)config 288 constraints:(const webrtc::MediaConstraintsInterface *)constraints 289 delegate:(id<RTCPeerConnectionDelegate>)delegate { 290 NSParameterAssert(factory); 291 if (self = [super init]) { 292 _observer.reset(new webrtc::RTCPeerConnectionObserver(self)); 293 _peerConnection = 294 factory->CreatePeerConnection(config, constraints, nullptr, nullptr, _observer.get()); 295 _localStreams = [[NSMutableArray alloc] init]; 296 _delegate = delegate; 297 } 298 return self; 299} 300 301- (rtc::scoped_refptr<webrtc::PeerConnectionInterface>)peerConnection { 302 return _peerConnection; 303} 304 305@end 306